Socat to UDP Server Truncating Last Character - character

So I am working on a Serial to UDP gateway to link a point of sale printer to a NVR that can overlay the transactions on the Camera video (When the POS unit prints on the serial printer, this unit taps into the serial data to the printer, then on the NVR screen you will see the text of what the serial printer.
Here is my code so far :
/usr/bin/socat -d -d -d -u file:/dev/ttyUSB0,b19200,nonblock exec:/usr/bin/strings |/usr/bin/socat -d -d -d -u - udp:10.0.1.3:37777,reuseaddr,sourceport=51470,reuseaddr
The first Socat instance reads the data going to the printer. Passes it to strings to strip the non ascii data, then the 2nd socat instance passes it onto the NVR.
This is working fine, however on the NVR, for some reason it is missing the last letter in each line. It might be reading the newline, and somehow ignoring the last character. What I need to do is figure out why it is doing this, or possibly easier, just add a dummy character before the newline character.
This is what the first socat and Strings produces
Thank you please call again
Gratuity........................
Total...........................
Please Do Not Accept Any
Hand Written Changes
To This Bill !!!
This is what the NVR is printing out
Thank you please call agai
Gratuity.......................
Total..........................
Please Do Not Accept An
Hand Written Change
To This Bill !!
A hexdump of what the first socat and strings produces is (the 0A i believe is the newline code)
00005030: 323a 3139 2054 6f74 616c 2044 7565 2020 2:19 Total Due
00005040: 2020 2020 2020 1b21 2032 3033 332e 3030 .! 2033.00
00005050: 1b21 000a 1b76 1b45 000a 1b45 0020 201b .!...v.E...E. .
00005060: 4500 2020 2020 5641 5420 2020 2020 2020 E. VAT
00005070: 2020 2020 2020 2020 2020 2020 2020 2020
00005080: 2032 3635 2e31 370a 1b76 1b45 000a 1b45 265.17..v.E...E
00005090: 0020 201b 4500 2020 2020 5468 616e 6b20 . .E. Thank
000050a0: 796f 7520 706c 6561 7365 2063 616c 6c20 you please call
000050b0: 6167 6169 6e0a 1b76 1b45 0020 201b 4500 again..v.E. .E.
000050c0: 2020 0a1b 761b 4500 2020 1b45 0020 2020 ..v.E. .E.
000050d0: 2047 7261 7475 6974 792e 2e2e 2e2e 2e2e Gratuity.......
000050e0: 2e2e 2e2e 2e2e 2e2e 2e2e 2e2e 2e2e 2e2e ................
000050f0: 2e0a 1b76 1b45 0020 201b 4500 2020 0a1b ...v.E. .E. ..
00005100: 761b 4500 2020 1b45 0020 2020 2054 6f74 v.E. .E. Tot
00005110: 616c 2e2e 2e2e 2e2e 2e2e 2e2e 2e2e 2e2e al..............
00005120: 2e2e 2e2e 2e2e 2e2e 2e2e 2e2e 2e0a 1b76 ...............v
00005130: 1b45 0020 201b 4500 2020 0a1b 761b 4500 .E. .E. ..v.E.
00005140: 2020 1b45 0020 2020 2050 6c65 6173 6520 .E. Please
00005150: 446f 204e 6f74 2041 6363 6570 7420 416e Do Not Accept An
00005160: 790a 1b76 1b45 0020 201b 4500 2020 2020 y..v.E. .E.
00005170: 4861 6e64 2057 7269 7474 656e 2043 6861 Hand Written Cha
00005180: 6e67 6573 0a1b 761b 4500 2020 1b45 0020 nges..v.E. .E.
00005190: 2020 2054 6f20 5468 6973 2042 696c 6c20 To This Bill
000051a0: 2121 210a 1b76 1b45 000a !!!..v.E..
Thanks for any help

Related

Problems with empty cell in a large matrix: MATLAB

I have a large matrix of 102730 rows in the form of text file (sample text file is attached) with some header files in it. The first column show year, the next the month, followed by the day, and value1, value2 and value 3. Some of the cells are missing/empty. I want to fill these empty cells with NaN, so that they don't interefere with the next value.
This is the input matrix:
1970 01 13 21.0 6.1 06 000.0
1970 01 14 22.4 8.1 03 000.0
1970 01 15 21.2 8.1 04 000.0
1970 01 16 22.6 9.1 04 000.0
1970 01 17 22.8 9.1 02 000.0
1970 01 18 22.9 8.9 07 000.0
1970 01 19 23.8 10.8 04 000.0
1970 01 20 21.8 12.1 10 010.5
1970 01 21 19.8 06 012.9
1970 01 22 15.3 8.5 07 000.0
1974 06 28 39.2 25.6 03 000.0
1974 06 29 41.2 30.5 05 000.0
1974 06 30 40.3 31.2 07 000.0
1974 07 01 41.3 31.5 12 000.0
1974 07 02 43.3 31.3 20 000.0
1974 07 03 41.2 16 041.6
1974 07 04 34.3 21.4 14 054.5
1974 07 05 33.1 23.8 05 000.0
1974 07 06 36.2 28.9 06 000.0
1975 04 18 36.6 20.8 12 000.0
1975 04 19 37.4 21.1 05 000.0
1975 04 20 39.9 27.0 07 000.0
1975 04 21 39.5 27.3 09 000.0
1975 04 22
1975 04 23 39.5 27.1 08 000.0
1975 04 24 37.7 26.0 10 000.0
1975 04 25 38.7 27.2 15 000.0
The desired output matrix:
1970 01 13 21.0 6.1 06 000.0
1970 01 14 22.4 8.1 03 000.0
1970 01 15 21.2 8.1 04 000.0
1970 01 16 22.6 9.1 04 000.0
1970 01 17 22.8 9.1 02 000.0
1970 01 18 22.9 8.9 07 000.0
1970 01 19 23.8 10.8 04 000.0
1970 01 20 21.8 12.1 10 010.5
1970 01 21 19.8 Nan 06 012.9
1970 01 22 15.3 8.5 07 000.0
1974 06 28 39.2 25.6 03 000.0
1974 06 29 41.2 30.5 05 000.0
1974 06 30 40.3 31.2 07 000.0
1974 07 01 41.3 31.5 12 000.0
1974 07 02 43.3 31.3 20 000.0
1974 07 03 41.2 Nan 16 041.6
1974 07 04 34.3 21.4 14 054.5
1974 07 05 33.1 23.8 05 000.0
1974 07 06 36.2 28.9 06 000.0
1975 04 18 36.6 20.8 12 000.0
1975 04 19 37.4 21.1 05 000.0
1975 04 20 39.9 27.0 07 000.0
1975 04 21 39.5 27.3 09 000.0
1975 04 22 Nan Nan Nan Nan
1975 04 23 39.5 27.1 08 000.0
1975 04 24 37.7 26.0 10 000.0
1975 04 25 38.7 27.2 15 000.0
As an attempt, first I tried with this:
T = readtable('sample.txt') ;
Above code didn't work since it meshed up and gave the wrong number of columns when there 2 digits before the decimal. Secondly, I found this link: Creating new matrix from cell with some empty cells disregarding empty cells
The foll. code snippet may be useful from this link, but I don't know how to read the data directly from the text pad inorder to apply this code & subsequent retrieval process:
inds = ~cellfun('isempty', elem); %elem to be replaced as sample
I also find out the method to detect empty cells here: How do I detect empty cells in a cell array?
but I couldn't figure out how to read the data from a text file considering these empty cells.
Could anyone please help?
Since R2019a, you can simply use readmatrix:
>> myMat = readmatrix('sample.txt')
From the docs:
For delimited text files, the importing function converts empty fields in the file to either NaN (for a numeric variable) or an empty character vector (for a text variable). All lines in the text file must have the same number of delimiters. The importing function ignores insignificant white space in the file.
For previous releases, you can use detectImportOptions object when calling readtable:
% Detect options.
>> opts = detectImportOptions('sample.txt');
% Read table.
>> myTable = readtable('sample.txt',opts);
% Visualise last rows of table.
>> tail(myTable)
ans =
8×7 table
Var1 Var2 Var3 Var4 Var5 Var6 Var7
____ ____ ____ ____ ____ ____ ____
1975 4 18 36.6 20.8 12 0
1975 4 19 37.4 21.1 5 0
1975 4 20 39.9 27 7 0
1975 4 21 39.5 27.3 9 0
1975 4 22 NaN NaN NaN NaN
1975 4 23 39.5 27.1 8 0
1975 4 24 37.7 26 10 0
1975 4 25 38.7 27.2 15 0
For your text file, detectImportOptions is filling missing values with NaN :
>> opts.VariableOptions
If the desired output is a matrix, you can then use table2array:
>> myMat = table2array(myTable)

Reading timeseries from multiple csv files in a folder: MATLAB

I have a bunch of csv files in a folder in following format, I want to extract complete time series from each (the numeric part from line #17), identify duplicate record and merge them in a ascending order according to year and date.
Specific csv file is accessible via google drive link below
wnsnum 1
paroms Waterhoogte
loccod HOEKVHLD
locoms Hoek van Holland
rks_begdat 1993 07 09
rks_begtyd 00:00
rks_enddat 2014 31 12
rks_endtyd 23:50
begdat begtyd enddat endtyd rkssta
1993 07 09 00:00 2007 31 12 23:50 D
2008 01 01 00:00 2009 30 12 23:50 G
2009 31 12 00:00 2009 31 12 23:50 O
2010 01 01 00:00 2011 17 06 18:40 G
2011 17 06 18:50 2011 18 06 18:50 O
2011 18 06 19:00 2014 31 12 23:50 G
datum tijd bpgcod waarde kwlcod
1993 07 09 00:00 -70 0
1993 07 09 00:10 -69 0
1993 07 09 00:20 -68 0
1993 07 09 00:30 -67 0
1993 07 09 00:40 -68 0
1993 07 09 00:50 -70 0
1993 07 09 01:00 -69 0
1993 07 09 01:10 -69 0
1993 07 09 01:20 -68 0
1993 07 09 01:30 -67 0
1993 07 09 01:40 -65 0
1993 07 09 01:50 -64 0
1993 07 09 02:00 -62 0
1993 07 09 02:10 -61 0
1993 07 09 02:20 -61 0
1993 07 09 02:30 -59 0
1993 07 09 02:40 -58 0
1993 07 09 02:50 -55 0
Now my code is working in a following way:
SL_files = dir(sprintf('%s%s%s',fullfile(dirName),'\','*.csv'));
for idx = 1:size(SL_files,1)
disp(SL_files(idx,1).name)
fid = fopen(sprintf('%s%s%s',fullfile(dirName),'\',SL_files(idx,1).name));
data = textscan(fid, '%s %f %f %f %f %f %f', ...
'Delimiter',',', 'MultipleDelimsAsOne',1,'headerlines',16);
fclose(fid);
end
Now I could read the file. Now my problem is how to combine multiple files' data into one matrix and arrange them in a ascending order according to year and day values. Thanks!
I finally solve my problem. Here is the code:
numMat_All = [];
for idx = 1:size(SL_files,1)
disp(SL_files(idx,1).name)
fid = fopen(sprintf('%s%s%s',fullfile(dirName),'\',SL_files(idx,1).name));
data = textscan(fid, '%s %f %f %f %f %f %f', ...
'Delimiter',',', 'MultipleDelimsAsOne',1,'headerlines',16);
fclose(fid);
CharCell = data{1,1};
result = regexprep(CharCell,'[\s;:]+',' ');
numMat = cell2mat(cellfun(#str2num, result(:,1:end), 'UniformOutput', false));
numMat_All = [numMat_All;numMat];
data = []; CharCell = []; result = []; numMat = [];
end
dt = datetime([numMat_All(:,1:5), repmat(0,length(numMat_All),1)]);
T = table(dt,numMat_All(:,[6:7]));
T1 = sortrows(T,'dt');

Check if file exists on a Cisco switch

I am trying to check if a file exists on the internal flash:/ disk of a Cisco switch.
switch-2950#dir flash:/
Directory of flash:/
2 -rwx 3721946 Jul 24 2009 16:17:10 +00:00 c2950-i6k2l2q4-mz.121-22.EA13.bin
3 -rwx 2035 Mar 01 1993 00:25:01 +00:00 config.text
5 drwx 4416 Jul 24 2009 16:19:50 +00:00 html
6 -rwx 556 Mar 01 1993 00:49:35 +00:00 vlan.dat
335 -rwx 315 Jul 24 2009 17:43:37 +00:00 env_vars
21 -rwx 112 Jul 24 2009 16:10:20 +00:00 info
22 -rwx 112 Jul 24 2009 16:20:56 +00:00 info.ver
23 drwx 64 Mar 01 1993 00:00:11 +00:00 crashinfo
25 -rwx 13495 May 18 2011 19:57:30 +00:00 config.old
336 -rwx 3832 Mar 01 1993 00:25:01 +00:00 private-config.text
7741440 bytes total (2124800 bytes free)
vlan.dat clearly exists. I can perform operations against it (such as copy).
However, I want to test if that particular file exists before performing
operations against it.
I am trying:
if os.path.isfile("flash:/vlan.dat"):
But it always returns False and the commands inside the 'if' statement are skipped over.
I have looked over numerous posts but they all cover Linux or Windows. I can't find anything regarding a Cisco file system.
I solved it another way. I do a 'dir flash:/', then I check for the existence
of the 'vlan.dat' file.
today = time.strftime("%x")
timenow = time.strftime("%X")
filename = (hostname + '-' + '%s' + '_' + '%s') % (today, timenow)
filename = filename.replace("/", "-")
filename = filename.replace(":", "-")
ssh_channel.send("dir flash:/" + "\n")
time.sleep(0.3)
outp = ssh_channel.recv(2000)
output = outp.decode("utf-8")
if 'vlan.dat' in output:
ssh_channel.send("copy flash:/vlan.dat tftp://192.168.1.106/" + filename + ".dat" + "\n")
time.sleep(0.3)

sed search and replace specific column only

Im taking weather day from wunderground.com and I and then trimming down the data for use on gnuplot. Im having trouble replacing the second column only data from number to months abbreviations. Only interested in the second column.
I want to go from this;
>2013 08 02 23 37 00 73.3
>2013 08 02 23 42 00 73.4
>2013 08 02 23 45 00 73.3
>2013 08 02 23 47 00 73.1
>2013 08 02 23 52 00 73.1
>2013 08 02 23 57 00 73.1
To this:
>2013 AUG 02 23 37 00 73.3
>2013 AUG 02 23 42 00 73.4
>2013 AUG 02 23 45 00 73.3
>2013 AUG 02 23 47 00 73.1
>2013 AUG 02 23 52 00 73.1
>2013 AUG 02 23 57 00 73.1
i am trying to use sed to change the numbers into the correct month and i keep getting this. I only want the correct sed expression to execute not all of them. This is the command i am trying to use.
sed -e 's/01/JAN/' -e 's/02/FEB/' -e 's/03/MAR/' -e 's/04/APR/' -e 's/05/MAY/' -e 's/06/JUN/' -e 's/07/JUL/' -e 's/08/AUG/' -e 's/09/SEP/' -e 's/10/OCT/' -e 's/11/NOV/' -e 's/12/DEC/'
How would i go about this.
This might work for you (GNU sed):
sed -nri 'G;s/$/01JAN02FEB03MAR04APR05MAY06JUN07JUL08AUG09SEP10OCT11NOV12DEC/;s/ (..)(.*)\1(...)/ \3\2/;P' file
This adds a lookup table to the end of each line and substitutes the key for the value.
I would use awk for this:
$ awk 'BEGIN{split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",a)} {$2=a[$2+0]}1' a
>2013 Aug 02 23 37 00 73.3
>2013 Aug 02 23 42 00 73.4
>2013 Aug 02 23 45 00 73.3
>2013 Aug 02 23 47 00 73.1
>2013 Aug 02 23 52 00 73.1
>2013 Aug 02 23 57 00 73.1
To update the field with the new content, just redirect and then move:
awk .... file > temp_file && mv temp_file file
Explanation
What we do is to give awk a list of strings with the months names. Once we convert it into an array, a[1] will be Jan, a[2] Feb and so on. So then it is just a matter of replacing the 2nd field with a[2nd field].
BEGIN{split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",a)} fetches the data and inserts into the a[] array.
{$2=a[$2+0]} sets the 2nd field as a[2nd field]. The $2+0 is done to convert 08 to 8.
Finally 1 evaluates as true and makes awk perform its default action: {print $0}.
Workaround that works for this problem (since your first column is very predictable) but not the general question:
sed -E -e 's/^([0-9]{4}) 01/\1 JAN/' -e 's/^([0-9]{4}) 02/\1 FEB/' etc.
awk has a sub function that could get unwieldy for many options you have here.
Perl scripts might be the best way to go.
$ awk '{$2=substr("JanFebMarAprMayJunJulAugSepOctNovDec",(3*$2)-2,3)}1' file
>2013 Aug 02 23 37 00 73.3
>2013 Aug 02 23 42 00 73.4
>2013 Aug 02 23 45 00 73.3
>2013 Aug 02 23 47 00 73.1
>2013 Aug 02 23 52 00 73.1
>2013 Aug 02 23 57 00 73.1
Since it came up in a comment:
The idiomatic awk way to map from a month number to a name is:
number = (match("JanFebMarAprMayJunJulAugSepOctNovDec",<name>)+2)/3
and the above is just the natural inverse of that:
name = substr("JanFebMarAprMayJunJulAugSepOctNovDec",(3*<number>)-2,3)
Like with anything in awk there's various ways to get the output you want but IMHO the symmetry here makes it an attractive solution:
awk 'BEGIN{
months = "JanFebMarAprMayJunJulAugSepOctNovDec"
name = "Jul"
number = (match(months,name)+2)/3
print name " -> " number
name = substr(months,(3*number)-2,3)
print number " -> " name
}'
Jul -> 7
7 -> Jul
Notice that the script uses the same definition for months no matter which direction the conversion is being done and it's a similar math calculation in both directions.
Nothing wrong with doing it this way too of course:
awk 'BEGIN{
split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",num2name)
for (number in num2name) {
name2num[num2name[number]] = number
}
name = "Jul"
number = name2num[name]
print name " -> " number
name = num2name[number]
print number " -> " name
}'
Jul -> 7
7 -> Jul
Just a few more lines of code, nbd.
Using gnu awk's function strftime() and mktime()
awk '{$2=strftime("%b",mktime("2014 " $2 " 1 1 0 0"))}1' file
>2013 Aug 02 23 37 00 73.3
>2013 Aug 02 23 42 00 73.4
>2013 Aug 02 23 45 00 73.3
>2013 Aug 02 23 47 00 73.1
>2013 Aug 02 23 52 00 73.1
>2013 Aug 02 23 57 00 73.1
Explanation
mktime("2014 " $2 " 1 1 0 0") fake the epoch time, use the column 2 as month
strftime("%b",mktime("2014 " $2 " 1 1 0 0")) convert the epoch back to the date, with %b, export the abbreviated month name (Jan, Feb, etc)
The benefit with this awk:
It is shorter, of course. Second, you can control/adjust the format in strftime() to export any date format you like.
For example, if change to full month name %B. You needn't rewrite the code.
awk '{$2=strftime("%B",mktime("2014 " $2 " 1 1 0 0"))}1' file

Print ping response time while higher than a fixed value, including date

I like to have a running ping that only prints output while passing a threshold value.
And if passing this value, also add date to the output.
Here is what I have tried:
ping 8.8.8.8 | awk '{split($7,a,"[=.]");if (a[2]>58) print a[2],d}' d="$(date)"
ping 8.8.8.8 | awk '{"date"| getline date;split($7,a,"[=.]");if (a[2]>58) print a[2],date}'
Problem with both of these is that date is not updated. All is printed with same date.
59 Fri Nov 15 08:55:04 CET 2013
59 Fri Nov 15 08:55:04 CET 2013
59 Fri Nov 15 08:55:04 CET 2013
60 Fri Nov 15 08:55:04 CET 2013
59 Fri Nov 15 08:55:04 CET 2013
I know this could be solved using a bash script, but I just like to have a simple command line when testing line ping time.
The following works for me. I'm using OSX Mavericks:
ping 8.8.8.8 | awk -F"[= ]" '{if($10>50) {cmd="date"; cmd | getline dt; close(cmd) ; print $10, dt}}'
This will output the ping line for times > 50 ms.
I get this sample output:
51.352 Fri Nov 15 00:33:40 PST 2013
50.519 Fri Nov 15 00:33:42 PST 2013
52.407 Fri Nov 15 00:33:44 PST 2013
50.904 Fri Nov 15 00:33:50 PST 2013
52.864 Fri Nov 15 00:33:54 PST 2013
When you say:
ping 8.8.8.8 | awk '{split($7,a,"[=.]");if (a[2]>58) print a[2],d}' d="$(date)"
the variable d is evaluated only once due to which you get the same timestamp appended to all the lines in the output. You could instead use strftime as an argument to print:
ping 8.8.8.8 | awk '{split($7,a,"[=.]");if (a[2]>58) print a[2], strftime()}'