node-serialport icon indicating copy to clipboard operation
node-serialport copied to clipboard

Changing parity on the fly

Open ficzusistvan opened this issue 9 years ago • 26 comments

SerialPort version: 4.0.1 NodeJS Version: v4.2.6 Operating System and Hardware: Raspbian Are you using Electron/Atom/NwJS?: no

(Run node -v && npm -v && python --version to get version numbers) v4.2.6 2.14.12 Python 2.7.9

Summary of Problem

As stated in the documentation for serialPort.update([options], [callback]) only baudRate is currently supported. In my project I would like to send data with parity 'space', but the only way to achieve this on Linux is to change parity on the fly between parity 'even' and 'odd', depending on the bits to send.

Requested Behavior

serialPort.update([options], [callback]) should support parity selection beside baudrate changing.

ficzusistvan avatar Sep 08 '16 13:09 ficzusistvan

@reconbot We have the same issue. There is a need to change parity from Mark to Space and Space to Mark depending on the payload. is there a date for this fix ?

NaveenChander avatar Jan 23 '19 23:01 NaveenChander

It needs a champion, someone to build it.

reconbot avatar Jan 24 '19 01:01 reconbot

needs this feature too any update or workaround ?

emeryao avatar Dec 09 '20 09:12 emeryao

Is there still demand for this feature? I'd be happy to try to code for this, however I don't have a usecase or sensible means to test it, so would need some support to test this before it could be deployed

GazHank avatar Jul 05 '21 20:07 GazHank

Hi here is my scenario

I have two same devices connected to the same two line of a RS485 bus line and then connected to a PC with a 485-usb cable

I have to send a command to the serial port with mark parity to activate the device with a device address and then send a query command to serial port with space parity to get some data from the activated device

I actually worked around with this awesome lib by open port / write data / close port / new another port with other parity / write data

It works well just with a few more codes but changing parity on the fly would definitely be better for coding experience

image

image

sample commands

# query device 1
// active device with address 01
send -> FF01FF // mark parity
receive <- FF01FF // device activated
send -> AAFF // space parity
receive <- SOME_DATA_FROM_01

# query device 2
// active device with address 02
send -> FF02FF // mark parity
receive <- FF02FF // device activated
send -> AAFF // space parity
receive <- SOME_DATA_FROM_02

Sorry for my poor English

emeryao avatar Jul 10 '21 11:07 emeryao

@Emeryao absolutely no need to appologise! Excellent English, and not only great info, but images and diagrams too!

I'm interested to take a look at the code and see how big a change this would be, and if we can get it to work on all platforms. What operating system(s) are using? While at first glance it looks like the code should use cross platform logic it would be good to initially target platform(s) where we have people interested in testing the new code :-)

@reconbot Do you have any preference for which method we use for this? I was thinking of extending the Set and Get methods for this feature, but either Update or a new method could also work. I don't think WebSerial account for this fuctionality, so don't think there is an option of following a standard for this yet, and therefore I assume we need to set the standard

GazHank avatar Jul 10 '21 22:07 GazHank

in my scenario it's a laptop with Windows 10 64bit and I actually wrap the codes to an Elecrton app to communicate with serial port

@GazHank

emeryao avatar Jul 11 '21 01:07 emeryao

Hi @Emeryao, I've created a fork with some initial changes to achieve the parity change functionality at https://github.com/GazHank/node-serialport/tree/parity-change

At the moment this is very limited so we can check if this works. So far:

  • Set method extended with parity option
  • Get method extended with parity info (although just returning an int at the moment rather than the descriptive value)
  • Both methods are updated for windows only at this stage (it turns out that I was mistaken and the logic will be platform specific)

Next steps (TODO):

  • Update methods for Linux
  • Update methods for MacOS
  • Only try to Set the parity if the user requests a change (at present it will trigger every time)
  • Revise the get method to return a string rather than the parity emun value

I can't really test it this works myself other than monitoring the data over the port as I don't have any devices that are parity dependant, so it would be great if you can check if it works for you

@reconbot if you have any suggestions or guidence on how best to share experimental functionality then please shout, I would like to make sure we can get some robust testing of this functionality before it is promoted to avoid any issues

GazHank avatar Jul 11 '21 16:07 GazHank

We need to know if all platforms support changing this on the fly. It's not a usual thing to change. Get/set/update are a mishmash of apis. I'll have to give it some thought.

reconbot avatar Jul 11 '21 17:07 reconbot

We need to know if all platforms support changing this on the fly. It's not a usual thing to change. Get/set/update are a mishmash of apis. I'll have to give it some thought.

I've mocked up the code for unix platforms but haven't had chance to compile it yet. If anything unix seems more likely to support this since it has the options to initiate the changes immediately, wait until the data has drained, or flush the existing data and apply the changes. I've drafted the update based on draining the existing data, but can always change that.

With some luck Mac will work using the unix code and won't need any extra changes 🤞🏼

GazHank avatar Jul 11 '21 18:07 GazHank

A branch with draft changes for the unix platforms is available at https://github.com/GazHank/node-serialport/tree/parity-change-unix but I don't know when I will get chance to test this out on Linux, so it's available for anyone you would like to take a look and progress this in my absence.

Since both Linux and Mac os appear to use the same logic for setting parity when opening a port (tcsetattr) it looks like this single change should work for both platforms, however there are already some mac os specific comments related to this method call, so it will need to be tested

GazHank avatar Jul 11 '21 21:07 GazHank

@Emeryao would you be able to test if the windows code works for you?

if you clone the windows only branch into a folder alongside you project then you should be able to test the code by adding a resolution into your package.json per below:

    "dependencies": {
        "serialport": "^9.2.0"
    },
    "resolutions": {
        "@serialport/bindings": "file:./../node-serialport/packages/bindings"
    }

By along side I mean that the above assumes that if your project is stored at "c:\abcxyz\myproject" then the clone of the test branch is stored at "c:\abcxyz\node-serialport"

Since this is the source code it will need to be compiled from source. Let me know if you need instructions or support with that.

GazHank avatar Jul 12 '21 19:07 GazHank

@ficzusistvan and @NaveenChander are you also interested in this functionality on Windows, or do you have any need for this on other platforms?

At the moment the Unix platforms (Linux and Mac) don't even support a parity of 'space' (or 'mark') therefore I'm inclined to consider this a windows only feature request. If anyone has any non-windows usecases then please shout otherwise I will consider this windows specific (in the same way that low latency mode is currently Linux specific)

GazHank avatar Jul 12 '21 19:07 GazHank

Thanks for taking time and looking into it !!! In my specific case Unix is fine as I use raspberry pi for the most part

NaveenChander avatar Jul 12 '21 20:07 NaveenChander

@NaveenChander Do you have a situation where you need to change between odd, even and none on the fly? or do you require the ability to set parity to 'space' for this to be useful?

Since we currently don't support parity of 'space' or 'mark' on Linux; I fear we may need to first consider implementing those parity settings before this would be useful for you?

Ps - i should also call out that space and mark parity settings don't seem to be documented as supported under linux or mac (therefore in order to add them we probably need to call them out as unsupported features which users can try at their own risk???)

GazHank avatar Jul 12 '21 20:07 GazHank

In my case I had to switch between space and mark parity. I work for a casino company and all slot machines work based on this. This was a protocol that was written almost 20+ years back and it is hard to replace existing all slot machines and I am stuck with it.

NaveenChander avatar Jul 12 '21 20:07 NaveenChander

Thanks for the speedy response @NaveenChander I'll see if space and mark parity settings can be added to unix too. Would you be able to test on Linux / raspberry pi if I can share an updated fork with you?

@reconbot are you comfortable if we include the additional parity settings for unix but document them as unsupported/ hardware dependent?

GazHank avatar Jul 12 '21 21:07 GazHank

I'm pretty sure those settings don't work on Mac or Linux. They're very... old hardware specific parities. I got some extra info here https://tldp.org/HOWTO/Serial-HOWTO-20.html#ss20.3

We can try to support them in the platform specific bindings. I'm comfortable.

reconbot avatar Jul 12 '21 22:07 reconbot

@NaveenChander I've updated the unix fork if you would like to test this? It includes space and mark functionality on supported systems (based on #if defined(CMSPAR))

you should be able to use the same resolution approach I suggested earlier, and if you are using raspberry Pi I assume you are pretty well setup to build from source, but please shout if you need any assistance

You might want to play with the settings for tcsetattr since I'm not sure if you want to use now, flush or drain : https://github.com/GazHank/node-serialport/blob/6660a0d2aeaec632894847bafc7bbb2e6d4d9a5d/packages/bindings/src/serialport_unix.cpp#L407-L413

you can find more info about that setting @ https://www.gnu.org/software/libc/manual/html_node/Mode-Functions.html

While it does seem that I can set the parity to space or mark on Linux (ubuntu LTS seems to allow this), I can't be certain if this really works as intended, since I don't have any suitable old hardware to hand (slot machines or otherwise). I'm also not sure if changing parity on the fly works on linux for the same reason. Per @reconbot I don't think mac os supports this at all - hopefully #if defined(CMSPAR) identifies supported systems, but I'd like to make sure we check this

GazHank avatar Jul 12 '21 22:07 GazHank

It looks like we should try to address https://github.com/serialport/node-serialport/issues/1113 as part of any change for this issue...

Depending on where we land with this issue, I'll try to update the docs to match the changes and give extra info on the platforms which support the different settings

GazHank avatar Jul 12 '21 23:07 GazHank

I'm sorry but the very device I mentioned above is at the site of one of our clients which is not reachable for me now 😅

emeryao avatar Jul 15 '21 08:07 emeryao

Thanks for the heads up @Emeryao

I will await testing feedback from yourself or one of the other users; I appreciate that physical access to devices is a little more challenging at the moment.

Since we have a testable fork for windows and unix, I won't create a pull request for this until we have some successful test results

GazHank avatar Jul 15 '21 09:07 GazHank

Hi! I wanted to circle back on this thread -- was this ever implemented into the main branch?

I have a need to support changing parity on the fly as well (similar, in the casino industry). However, when calling port.update(), I can't pass in parity. It seems to only allow changes to baudRate.

Is there any way to change the parity on the fly?

(I attempted to merge the changes from @GazHank , even manually -- but it looks like the serialport code has been significantly refactored since the earlier commits, so the files don't even exist anymore)

I have full access to machines and I'll be able to test immediately on macOS and RPi. Let me know, thanks!

mikeho avatar Feb 10 '24 16:02 mikeho

Okay, so a bit more context about this:

  • The protocol we have (known as the SAS (Slot Accounting System) protocol) requires certain bytes to be sent with mark parity, and other bytes to be sent with space parity.
  • Unfortunately, linux/unix-based OS's (including RPi and macOS) have a bit of a spotty record being able to handle mark and space.
  • So logically, the workaround is to analyze each byte being sent, manually checking the parity, and depending if it needs to be sent as mark or space, to actually set the port to be even or odd parity based on the parity of the byte.

What this means is that we would like to be able to do on-the-fly switching of the parity between even and odd.

But it doesn't seem that SerialPort has this capability out-of-the-box -- when calling port.update(), the only setting I am able to change is baudRate?

Fortunately, I've been able to do a workaround where I literally just close the port, and then re-open the port with the new settings whenever I need to switch from even to odd (or vice versa). I've attached the proof-of-concept code which uses port.close() and re-creates/re-opens the port whenever we need to switch parity. At the very least, I can confirm that this does work. Basically, you can see in sendByte() is where we check the parity, and "switch" between even and odd parity prior to calling port.write().

However, I'm a bit nervous about having my app constantly closing and re-opening the port whenever the parity needs to be switched (which may end up being dozens of times per minute).

So it'd be great if this could be done, maybe via a call to .update()? (which would essentially replace lines 82-94 with just a single call to .update() and then my call to .write())

Appreciation for any assistance that can be provided on the matter. Thanks!!! index.js.txt

mikeho avatar Feb 10 '24 17:02 mikeho

Hello everyone! Just wanted to "bump" this and see if anyone would be able to take a look at this for us? We're more than happy to provide a modest bounty on successful implementation of this. Please let us know, thanks!

mikeho avatar Feb 16 '24 19:02 mikeho