Where is my interpretation of ASN1 der wrong? - encoding

Here is what my structure looks like:
SET OF
SEQUENCE:
INTEGER: XX
INTEGER: YY
My encoding looks like this:
11 08 10 06 02 01 XX 02 01 YY
11 08 -- SET OF
10 06 -- SEQUENCE
However, when I decode with openssl, I don't see the expected output. It looks like
0:d=0 hl=2 l= 8 prim: SET
0000 - 10 06 02 01 XX 02 01 YY-
This is not what I expected to see. (Look at the structure I wanted it to look like)
I am not sure what I am missing. Any help would be much appreciated.

A SET and SEQUENCE are constructed types. That means that the bit that indicates a constructed type in the tag needs to be set. That would be bit 5 or 6 (depending if you start with bit 0 or 1). If the bit isn't set then the parser will view it as a primitive type, which means it has a single value instead of children. This is why you get prim in your output. The tag number is still 17 or 16 which denotes a SET OF or SEQUENCE, so the structure is still seen to be a SET.
So instead of 11 and 10 you should be using values 31 and 30. Then your code should parse correctly.

Related

sending multiple bytes of data from pc serial port to custom hardware using matlab

I am using the following matlab program to send multiple serial port data through the PC using a USB-serial port
close all; clear all; clc;
array_1st = ones(64, 1, 'uint8');
array_1st = array_1st';
for i=1:64
array_1st(i) = array_1st(i) * i ;
end
dummy_var = zeros(1,1);
if ~isempty(instrfind)
fclose(instrfind);
delete(instrfind);
end
s=serial('COM9');
set(s,'Terminator','CR','DataBits',8,'Parity','none','StopBits',1,'baudrate', 38400);
fopen(s);
disp('fopen(s)');
fwrite(s, array_1st);
pause(0.5);
dummy_var = fread(s, 1);
dummy_var
fclose(s);
clear s
A custom hardware is connected to the serial port. I have already been able to read multiple bytes of data sent by the custom hardware in the PC using a similar matlab program (that is, multiple byte transfer from hardware -> PC through serial port using matlab is working)
I am expecting the code above to write an array of 8-bit unsigned ints when the fwrite(s, array_1st); function is executed. The custom hardware at this point displays the bytes received in the serial port in it's IDE's terminal and waits in a breakpoint before dummy_var = fread(s, 1); in the matlab program is called
The problem is matlab is always sending only the first byte of the array_1st array to the serial port hardware. I have tried all kinds of variations in the above program, such as removing the array_1st = array_1st'; line, using char instead of uint8, usinf LF for terminator property in the serial port object, but the problem is always same: only the first bte of the array being sent actually goes through the serial port hardware to the custom device.
After calling fwrite(s, array_1st);, matlab also the following warning:
Warning: The specified amount of data was not returned within the
Timeout period.
The properties of the serial object after the fopen():
Serial Port Object : Serial-COM9
Communication Settings
Port: COM9
BaudRate: 38400
Terminator: 'CR'
Communication State
Status: open
RecordStatus: off
Read/Write State
TransferStatus: idle
BytesAvailable: 0
ValuesReceived: 0
ValuesSent: 0
It's properties after executing the dummy_var = fread(s, 1); line are:
Serial Port Object : Serial-COM9
Communication Settings
Port: COM9
BaudRate: 38400
Terminator: 'CR'
Communication State
Status: open
RecordStatus: off
Read/Write State
TransferStatus: idle
BytesAvailable: 0
ValuesReceived: 0
ValuesSent: 64
The ValuesSent property has been updated to 64 from 0, which I guess is indicating that, at least as far as the matlab serial port object is concerned, 64 data are being sent, but for some reason only the 1st one is actually going through the serial port hardware
What could be the reason for this? Is it that matlab just doesn't support what I want to do? If only 1 data is getting sent through the serial port hardware, why does ValuesSent show 64?
Matlab version is R2009b
EDIT 1: -----
I recorded the serial object data using the serial/record function, and here is what it recorded:
Legend:
* - An event occurred.
> - A write operation occurred.
< - A read operation occurred.
1 Recording on 29-Jul-2018 at 23:27:19.241. Binary data in little endian format.
2 > 64 uchar values.
01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10
11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20
21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30
31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40
3 < 0 uchar values.
4 Recording off.

CRC-16 in MATLAB

I have a working program in LabVIEW that I want to port to MATLAB. It takes an input number, converts it to hex, appends it to a constant string (0110 0001 0002 0400 03), calculates a CRC-16, and sends it all to a COM port. Here are two examples for 1500 and 2000 respectively.
0110 0001 0002 0400 0305 DCC0 AA
0110 0001 0002 0400 0307 D0C1 CF
I can see that dec2hex(1500) produces the 5DC, and dec2hex(2000) produces the 7D0. The AA and the CF are produced by a CRC-16 LabVIEW program, which are 170 and 207 respectively. I understand these are some sort of check-sums, but I can't find a way to reproduce it in MATLAB.
Solution found via: FEX submission
A = ['01';'10';'00';'01';'00';'02';'04';'00';'03';'07';'D0']
dec2hex(append_crc(hex2dec(A)'))
Returns:
01
10
00
01
00
02
04
00
03
07
D0
C1
CF

How to group dates within a certain time interval

I have an array of dates and i would like to discard any dates that don't have at least one another date in a specific time interval, for example 5 minutes. I need to find a smart way to do it, as loops take forever with a larger dataset.
input data:
2009 07 07 16:01:30
2009 07 07 16:04:06
2009 07 07 16:05:00
2009 07 07 16:12:00
2009 07 07 16:19:43
2009 07 07 16:24:00
results:
2009 07 07 16:01:30
2009 07 07 16:04:06
2009 07 07 16:05:00
2009 07 07 16:19:43
2009 07 07 16:24:00
The value 2009 07 07 16:12:00 was discarded because it was more than 5 minutes away from any other timestamp.
Thanks,
Cristi
Secondary issue:
Both Dan and nkjt suggested an implementation that worked, thanks! What if the dates are part of 2 groups: A or B and i want to find if there exist a date from group A that has a corresponding date in group B that is within a number of seconds/minutes apart? if not just remove the date from group A..
You can use diff. You'll need to use datenum to convert your data into a vector of values. In MATLAB datenums, "1" is a single day, so you can define a datenum step in terms of a time unit divided by the number of those in a day:
s = num_mins/(24*60);
Here's the trick with diff:
x = datenum(mydata);
s = num_mins/(24*60);
% for increasing times we shouldn't need the `abs` but to be safe
d = abs(diff(x));
q = [d (s+1)]>s&[(s+1) d]>s;
(You can use datestr to convert back, or apply q to the original data)
How it works:
The output of diff is one shorter than the original - it's just the difference between neighbouring values. We need it to be directional - to check each value against the one that comes before and after.
[d (s+1)]>s makes a vector the same length as the original, and checks if the difference values are larger than s. Because we set the last value to be s+1, the final value will always return true. This is a check to whether there's a gap between a value and the one following it (so for the final value this is always true).
[(s+1) d]>s does the same but on the other side. Again, we are setting one value, this time the first, to be larger than s so it's always true.
Combining these gives us the points where the difference is more than five minutes on either side (or for the end points, on one side).

Stata longwise average

I'm using Stata and trying to compute conditional means based on time/date. For each store I want to calculate mean (inventory) per year. If there are missing year gaps, then I want to take the mean from the closest two dates' inventory values.
I've used (below) to get overall means per store, but I need more granularity.
egen mean_inv = mean(inventory), by (store)
I've also tried this loop with similar results:
by id, sort: gen v1'=_n'
forvalues x = 1/'=n'{
by store: sum inventory if v1==`x'
replace mean_inv= r(mean) if v1==`x'
}
Visually, I want mean inventory per store: (store id is not sequential)
5/1/2003 2/3/2006 8/9/2006 3/5/2007 6/9/2007 2/1/2008
13 18 12 15 24 11
[mean1] [mean2] [mean3] [mean4] [mean5]
store date inventory
1 16750 17
1 18234 16
1 15844 13
1 17111 14
1 17870 13
1 16929 13.5
1 17503 13
4 15987 18
4 15896 16
4 18211 16
4 17154 18
4 17931 24
4 16776 23
12 16426 26
12 17681 17
12 16386 17
12 16603 18
12 17034 16
12 17205 16
42 15798 18
42 16022 18
42 17496 16
42 17870 18
42 16204 18
42 16778 14
33 18053 23
33 16086 13
33 16450 21
33 17374 19
33 16814 19
33 15834 16
33 16167 16
56 17686 16
56 17623 18
56 17231 20
56 15978 16
56 16811 15
56 17861 20
It is hard to relate your code to the word description of your problem.
Your egen call calculates means by store, not year.
Your longer fragment does not make complete sense given lack of definitions and at least one typo.
Note that your variable v1 contains identifiers that run 1 up within groups of store, and does not distinguish different values of store, as you (seem to) imply. It strains credibility that it produces results anywhere near those by the egen call.
n is not defined and the code evaluating it is presumably intended to be
`=n'
If you calculate
by store: sum inventory if v1 == `x'
several means will be calculated in turn but only the last to be calculated will be accessible as r(mean).
The sample data are unrelated to the problem. There is no year variable and even if the dates are Stata daily dates, they are all dates within 1960.
Setting all that aside, suppose you have variables store, inventory and year. You can try
collapse inventory, by(store year)
fillin store year
ipolate inventory year, gen(inventory2) by(store)
The collapse produces a reduced dataset of means. The ipolate interpolates across gaps, as you ask. fillin may not be adequate to give all the store and year combinations you want and you may need to add further years manually before the interpolation. If you want to put these results back with the original data, that's a merge.
In total, this is a pretty messy question.

How to convert a large number to base 36 using DC or other

I am trying to represent the maximum 64-bit unsigned value in different bases.
For base 2 (binary) it would be 64 1's:
1111111111111111111111111111111111111111111111111111111111111111
For base 16 (hex) it would be 16 F's
FFFFFFFFFFFFFFFF
For base 10 (decimal) it would be:
18446744073709551615
I'm trying to get the representation of this value in base 36 (it uses 0-9 and A-Z). There are many online base converters, but they all fail to produce the correct representation because they are limited by 64-bit math.
Does anyone know how to use DC (which is an extremely hard to use string math processors that can handle numbers of unlimited magnitude) and know how to do this conversion? Either that or can anyone tell me how I can perform this conversion with a calculator that won't fail due to integer roll-over?
I mad a quick test with ruby:
i = 'FFFFFFFFFFFFFFFF'.to_i(16)
puts i #18446744073709551615
puts i.to_s(36) #3w5e11264sgsf
You may also use larger numbers:
i = 'FFFFFFFFFFFFFFFF'.to_i(16) ** 16
puts i
puts i.to_s(36)
result:
179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625
1a1e4vngailcqaj6ud31s2kk9s94o3tyofvllrg4rx6mxa0pt2sc06ngjzleciz7lzgdt55aedc9x92w0w2gclhijdmj7le6osfi1w9gvybbfq04b6fm705brjo535po1axacun6f7013c4944wa7j0yyg93uzeknjphiegfat0ojki1g5pt5se1ylx93knpzbedn29
A short explanation what happens with big numbers:
Normal numbers are Fixnums. If you get larger numbers, the number becomes a Bignum:
small = 'FFFFFFF'.to_i(16)
big = 'FFFFFFFFFFFFFFFF'.to_i(16) ** 16
puts "%i is a %s" % [ small, small.class ]
puts "%i\n is a %s" % [ big, big.class ]
puts "%i^2 is a %s" % [ small, (small ** 2).class ]
Result:
268435455 is a Fixnum
179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625
is a Bignum
268435455^2 is a Bignum
From the documentation of Bignum:
Bignum objects hold integers outside the range of Fixnum. Bignum objects are created automatically when integer calculations would otherwise overflow a Fixnum. When a calculation involving Bignum objects returns a result that will fit in a Fixnum, the result is automatically converted.
It can be done with dc, but the output is not extremely useful.
$ dc
36
o
16
i
FFFFFFFFFFFFFFFF
p
03 32 05 14 01 01 02 06 04 28 16 28 15
Here's the explanation:
Entering a number by itself pushes that number
o pops the stack and sets the output radix.
i pops the stack and sets the input radix.
p prints the top number on the stack, in the current output radix. However, dc prints any output with a higher radix than 16 as binary (not ASCII).
In dc, the commands may be all put on the same line, like so:
$ dc
36o16iFFFFFFFFFFFFFFFFp
03 32 05 14 01 01 02 06 04 28 16 28 15
Get any language that can handle arbitrarily large integers. Ruby, Python, Haskell, you name it.
Implement the basic step: modulo 36 gives you the next digit, division by 36 gives you the number with the last digit cut out.
Map the digits to characters the way you like. For instance, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'[digit] is fine by me. Append digits to the result as you produce them.
???
Return the concatenated string of digits. Profit!