Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hs.serial does not appear to receive serial data correctly #3310

Closed
sethvoltz opened this issue Nov 2, 2022 · 11 comments · Fixed by #3314
Closed

hs.serial does not appear to receive serial data correctly #3310

sethvoltz opened this issue Nov 2, 2022 · 11 comments · Fixed by #3314

Comments

@sethvoltz
Copy link

I am working on a custom Arduino-based macropad that takes status from Hammerspoon to update indicators and commands from the pad to update apps via Hammerspoon integrations and spoons. I am able to send serial data to the device but no messages are passed back to the callback. My setup is as follows:

The setup:
On the hardware side, I have a 32u4-based development board (Adafruit Itsy-Bitsy, 5V) with a test sketch that does a few things: reads serial and looks for "set" if that is followed by "on", it blinks the LED fast, otherwise it blinks it slowly. On switching, it prints back whether it was set fast or slow. It also has a button input that prints "button pressed".

On the Hammerspoon side, I have a simple setup that creates the serial port (hard coded path for testing), attaches a callback, and opens the port. It then attaches an app handler to look for when Hammerspoon is brought to the front to test serial recept bt the hardware. Lastly, it also has a timeout to close the port after 20 seconds so I don't need to quit Hammerspoon while testing in order to re-flash and use the other serial monitors.

What happens:
When I bring Hammerspoon console to the front, the LED blinks fast, when I switch to another app, it blinks slowly, indicating the remote hardware is receiving serial successfully. No messages are logged back or when I press the button.

What I expect to happen:
Whenever the apps switch, I expect to see a serial message logged. Whenever the button is pressed, I expect to see a serial message logged.

Control:
The serial messages work bidirectionally in all other serial consoles I have used.

Here is the complete Hammerspoon code:

local obj={}
obj.__index = obj

function serialWatcher(serialPortObject, callbackType, message, hexadecimalString)
  print("------------------------- serial event: " .. callbackType)
  if callbackType == "received" then
    print("message: " .. message)
  end
end

function sendToSerial(message)
  print("sending to serial:  " .. message)
  if obj.serial == nil or not obj.serial:isOpen() then
      print("not connected")
      return
  end
  obj.serial:sendData(message .. "\n")
end

function connectToUSB()
  print("----------------------------- connecting to USB")
  if obj.serial ~= nil and obj.serial:isOpen() then
      print("already connected")
      return
  end

  local path = "/dev/cu.usbmodem101"
  obj.serial = hs.serial.newFromPath(path)
  obj.serial:baudRate(115200)
  obj.serial:callback(serialWatcher)
  obj.serial:usesDTRDSRFlowControl(1) -- the docs say this should be boolean but only an int works, not sure if this is working
  obj.serial:usesRTSCTSFlowControl(1) -- the docs say this should be boolean but only an int works, not sure if this is working
  obj.serial:open()
end

function applicationWatcher(appName, eventType, appObject)
  if appName ~= nil and eventType == hs.application.watcher.activated then
      -- the following sends "set on" when the Hammerspoon console is brought forward
      sendToSerial("set " .. (appName == "Hammerspoon" and "on" or appName))
  end
end
obj.appWatcher = hs.application.watcher.new(applicationWatcher)
obj.appWatcher:start()

connectToUSB()

hs.timer.doAfter(20, function()
  print("------------------------ Closing serial")
  obj.serial:close()
end)

return obj
@sethvoltz
Copy link
Author

sethvoltz commented Nov 2, 2022

Just reloading now, here are the Hammerspoon logs for this file. I switched apps a few times and pressed the button a few times:

2022-11-02 12:49:49: -- Loading extension: application
2022-11-02 12:49:49: ----------------------------- connecting to USB
2022-11-02 12:49:49: -- Loading extension: serial
2022-11-02 12:49:49: -- Loading extension: pathwatcher
2022-11-02 12:49:49: -- Loading extension: notify
2022-11-02 12:49:49: -- Done.
2022-11-02 12:49:49: ------------------------- serial event: opened
2022-11-02 12:49:50: sending to serial:  set Google Chrome
2022-11-02 12:49:51: sending to serial:  set on
2022-11-02 12:49:53: sending to serial:  set Google Chrome
2022-11-02 12:49:53: sending to serial:  set on
2022-11-02 12:50:09: ------------------------ Closing serial
2022-11-02 12:50:09: ------------------------- serial event: closed

And here is in the PlatformIO serial terminal sending set on, set off and pressing the button a few times:

Setting LED fast
Setting LED slow
Button pressed
Button pressed
Button pressed
Button pressed

@latenitefilms
Copy link
Contributor

Ummm... that's strange. I use hs.serial quite a bit in CommandPost and it works fine there as far as I know. Although, I haven't tested recently on macOS Ventura.

Have you tried setting the hs.serial:dataBits() and hs.serial:stopBits()? Maybe the default values aren't suitable for your application>?

usesDTRDSRFlowControl and usesRTSCTSFlowControl is definitely a bug in checkArgs:

[skin checkArgs:LS_TUSERDATA, USERDATA_TAG, LS_TNUMBER | LS_TOPTIONAL, LS_TBREAK];

[skin checkArgs:LS_TUSERDATA, USERDATA_TAG, LS_TNUMBER | LS_TOPTIONAL, LS_TBREAK];

@latenitefilms
Copy link
Contributor

Actually... this is most likely your issue:

armadsen/ORSSerialPort#174 (comment)

@latenitefilms
Copy link
Contributor

You could try adding:

self.serialPort.RTS = YES;
self.serialPort.DTR = YES;

...here:

self.serialPort.usesDCDOutputFlowControl = self.usesDCDOutputFlowControl;

@cmsj
Copy link
Member

cmsj commented Nov 2, 2022

@latenitefilms should we just expose those through hs.serial's API?

@latenitefilms
Copy link
Contributor

Yes, I think so. I'm not entirely sure how best to document, as it's not really well documented in the pod's repo - but I'll try do a pull request later today.

@cmsj
Copy link
Member

cmsj commented Nov 2, 2022

@latenitefilms I would just document them as "control flow signals" - there is tons of info online about what RTS, DTR, CTS, etc. mean, they are very generic serial communication signals.
Edit: (ie people can go and look up what they are, for themselves)

@latenitefilms
Copy link
Contributor

I understand what they are, what I don't quite have my head around is how RTS and DTR differ from the existing usesDTRDSRFlowControl and usesRTSCTSFlowControl. But yes, agreed - I'll just expose them both.

@sethvoltz
Copy link
Author

@latenitefilms interesting find, yeah, that sounds exactly like the issue I'm having. It does seem to be a limitation of the microcontroller itself that requires RTS and DTR to be enabled. I did find that when I disabled both RTS and DTR that's when it wouldn't communicate correctly. Below is a session I just ran, starting with a new serial monitor, defaulting to both on. The messages between dashes are from the monitor itself, using the control commands to toggle flow control on and off. At each toggle, I would send a set <on/off> call, and press the physical button.

Setting LED fast
Button pressed
--- RTS inactive ---
Setting LED slow
Button pressed
--- DTR inactive ---
--- RTS active ---
Setting LED fast
Button pressed
--- DTR active ---
Setting LED fast
Button pressed

latenitefilms added a commit to latenitefilms/hammerspoon that referenced this issue Nov 3, 2022
- Added methods to get and set the `RTS` and `DTR` values.
- Fixed some inconsistencies in the documentation.
- Fixed some typos where `LS_TNUMBER` was incorrectly used instead of `LS_TBOOLEAN`.
- Closes Hammerspoon#3310
@latenitefilms
Copy link
Contributor

@sethvoltz - I've added a pull request which will HOPEFULLY resolve the issue you're having.

@cmsj cmsj closed this as completed in 0723af3 Nov 3, 2022
@cmsj cmsj closed this as completed in #3314 Nov 3, 2022
@sethvoltz
Copy link
Author

@latenitefilms Thank you! I can't wait to get it in the auto update. I'll report back here if it doesn't resolve the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants