j123b567 / scpi-parser

Open Source SCPI device library
BSD 2-Clause "Simplified" License
447 stars 191 forks source link

problem talking with sigrok #131

Closed folkertvanheusden closed 1 year ago

folkertvanheusden commented 2 years ago

Hi,

The example in scpi-parser/examples/test-tcp is not compatible with sigrok:

sr: [00:00.005751] hwdriver: sr_config_list(): key 2147418112 (NULL) sdi (nil) cg NULL -> [uint32 20000]
sr: [00:00.005794] serial: Parsed serial device: tcp-raw/localhost/5025.
sr: [00:00.005813] scpi: Opening RAW TCP device tcp-raw/localhost/5025.
sr: [00:00.006057] scpi_tcp: Successfully sent SCPI command: '*IDN?'.
sr: [00:00.006116] scpi: Got response: 'MANUFACTURE', length 11.
sr: [00:00.006131] scpi: IDN response not according to spec: 'MANUFACTURE'

I believe this seems to be caused by the '*IDN?' response to be send in multiple write-calls causing multiple tcp/ip packets which are received as multiple read()-calls.

recvfrom(4, "*IDN?\n", 10, 0, NULL, NULL) = 6
write(4, "MANUFACTURE", 11)             = 11
write(4, ",", 1)                        = 1
write(4, "INSTR2013", 9)                = -1 EPIPE (Broken pipe)

sigrok-test.pcap.zip

WyoOutlaw commented 2 years ago

The response from an IEEE 488.2 *IDN? is a single arbitrary string, that typically has 4 common separated fields (manufacturer, model, serial, version). It is incorrect to send them separately. Regards, Eric


From: folkertvanheusden @.> Sent: Thursday, November 18, 2021 11:07 AM To: j123b567/scpi-parser @.> Cc: Subscribed @.***> Subject: [j123b567/scpi-parser] problem talking with sigrok (Issue #131)

Hi,

The example in scpi-parser/examples/test-tcp is not compatible with sigrok:

sr: [00:00.005751] hwdriver: sr_config_list(): key 2147418112 (NULL) sdi (nil) cg NULL -> [uint32 20000] sr: [00:00.005794] serial: Parsed serial device: tcp-raw/localhost/5025. sr: [00:00.005813] scpi: Opening RAW TCP device tcp-raw/localhost/5025. sr: [00:00.006057] scpi_tcp: Successfully sent SCPI command: '*IDN?'. sr: [00:00.006116] scpi: Got response: 'MANUFACTURE', length 11. sr: [00:00.006131] scpi: IDN response not according to spec: 'MANUFACTURE'

I believe this seems to be caused by the '*IDN?' response to be send in multiple write-calls causing multiple tcp/ip packets which are received as multiple read()-calls.

recvfrom(4, "*IDN?\n", 10, 0, NULL, NULL) = 6 write(4, "MANUFACTURE", 11) = 11 write(4, ",", 1) = 1 write(4, "INSTR2013", 9) = -1 EPIPE (Broken pipe)

sigrok-test.pcap.ziphttps://github.com/j123b567/scpi-parser/files/7565022/sigrok-test.pcap.zip

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://github.com/j123b567/scpi-parser/issues/131, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AB5C3MDOARKBCH6IGR5EGRTUMU6FRANCNFSM5IKIEQBA. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

folkertvanheusden commented 2 years ago

@WyoOutlaw yes; at https://github.com/j123b567/scpi-parser/blob/master/libscpi/src/ieee488.c#L271 there's the code that emits it as 4 seperate mnemonics. Eventually https://github.com/j123b567/scpi-parser/blob/master/libscpi/src/parser.c#L361 is called which calls writeData and that ends with a call to a write() call. So that's not easy to fix.

folkertvanheusden commented 2 years ago

Well, you can disable(!) the 'TCP_NODELAY' socket option while processing *IDN? That way one can reasonably sure that the 4 packets are concatenated. See 2a1fbbd629e4c1d7f636bbb7817bea1ba082981a in the pull request.

j123b567 commented 2 years ago

The problem is on the sigrok site so the only correct solution is https://sigrok.org/bugzilla/show_bug.cgi?id=1750

TCP is stream protocol and underlaying packets are just unimportant technological detail. You should always depend on your message boundary (which is \n in SCPI). Unfortunately, many developers thing, that packets are important and they are doing the message boundaries, which is in case of TCP completely wrong assumption.

SCPI parser has API for this, so developer is free to implement output buffering. It is the reason, why there is separate write and flush callbacks. With write, you can write to your memory buffer and with flush, you can send the buffer over the wire.

You can also persuade the TCP stack not to send so often so it can buffer output messages for you.

Thank you @folkertvanheusden for both creating the sigrok issue and providing the TCP_NODELAY example.

j123b567 commented 1 year ago

Should be solved by #133 on our side.