firmata/ConfigurableFirmata

Feature Request: 433 Mhz tx/rx support

danielhep opened this issue · 16 comments

There are numerous cheap 433 Mhz receiver and transmitter pairs available on eBay. A common use for them is controlling remote controlled outlets like these ones.

There's a complete library available here which works very well for the Arduino. It would be fantastic to see this implemented in Firmata so we can see it in other platforms.

I'm not going to do this work, but hopefully someone will want to take it on. The one action item for me however is to write up guidelines for how to develop 3rd party Firmata modules. An example module is here, but it's not well documented: https://github.com/firmata/FirmataEncoder.

An implementation is available under https://github.com/git-developer/RCSwitchFirmata

@git-developer I could assigned this feature a dedicated ID (rather than having to use 0x00). One other change I'd suggest is removing the RC_SEND and RC_RECEIVE pin modes since I'm planning to deprecated pin modes for non-HW pin modes, also the values assigned would conflict with pin modes already in use. I've ordered some radio modules so this is something I could also help out with over the upcoming holiday break.

Sounds good. I would favor to see RCSwitchFirmata integrated. I remember that I tried in 2014, found an ancient pull request and the repos protocol and arduino forked. But it's been a long time since I developed the library, so I'll have to get my mind back into it.

When the pin modes are removed, what will be the replacement? Two distinct IDs?

This is the proposal for replacing the use of pin modes as a feature query: firmata/protocol#91. So in the case of RCSwitchFirmata we'd either need 2 IDs (1 for input and 1 for output), or combine input and output into a single class and use a single ID.

I've reviewed a lot this week, found

It's quite hard for me to follow all this. I'm still trying to find out what of all this is relevant to RCSwitchFirmata. Let me sum up what I think now:

  1. RCSwitchFirmata can be categorized as an optional feature (in contrast to core features)
  2. Optional features get a centrally assigned sysex command ID that differs from (and does not start with) 0x00. They are listed in the feature registry.
  3. Currently:
    • Both RCInputFirmataand RCOutputFirmata share RESERVED_COMMAND (0x00) as sysex command ID.
    • handleCapability() is used to report capabilities to the host and returns the pin mode.
    • handlePinMode() is used to enable and disable a feature
    • handleSysex() is used for the main logic
  4. The classes RCInputFirmata and RCOutputFirmata are distinct:
    • Both classes don't depend on each other.
    • Configuration and behavior are distinct.
    • Hardware requirements differ: digital pin and 433 MHz sender for output, interrupt pin and 433 MHz receiver for input.
    • Users may use either one or both or none.

If all of this is correct, I suppose to use one feature ID for RCInputFirmata and another one for RCOutputFirmata. Using a single feature ID for both features wouldn't feel right for me.

The next steps would be per feature:

  1. Request a proposed Feature ID and replace RESERVED_COMMAND
  2. Create a pull request against firmata/protocol that adds protocol description to protocol.md
  3. Change Arduino code and bundle it as a separate Arduino library (not hosted in an official firmata repository) that may be used in conjunction with the libraries ConfigurableFirmata and rcswitch
  4. Adapt client code to these changes (I'm wrote a perl client for FHEM)

Open questions:

  1. Is this all correct?
  2. What happens to handlePinMode()?
  3. How are features enabled and disabled?

In response to your assumptions above:

  1. Request 2 feature IDs, 1 for RCInputFirmata and 1 for RCOutputFirmata
  2. Create a pull request against firmata/prototcol, adding a new rcswitch-proposal.md file
  3. This is correct

What happens to handlePinMode()?

Since this feature will most likely land before the feature query is implemented (since I'm debating whether to include the new feature query it in the near future or defer it to Firmata 3.0), if you need pin modes for discovery purposes then we'll have to add them. If however the pin modes aren't absolutely necessary then simply return false from handlePinMode and stub handleCapability. The problem with pin modes as a firmware feature query is it doesn't scale well, with a high pin count board like an Arduino Mega and a few features enabled you're looking a a capability query response in excess of 500 bytes. Some client library developers have had to add 'skip capability query' functionality to avoid crashes in the case of users including a lot of features. The proposed feature query will scale much better and individual pins per feature could be requested separately if necessary.

How are features enabled and disabled?

I'm not exactly sure what you mean. Individual features are either included or not included in the sketch at compile time. You could add attach and detach methods like in the FirmataEncoder example although dynamic memory allocation can cause issues on limited RAM microcontrollers.

Once upon a time, when I wrote RCSwitchFirmata, my understanding was:

  • every Firmata feature uses pin modes
  • handleCapability() is used to tell the host about the presence of a feature by returning its pin mode
  • handlePinMode() is used to enable/disable a feature for a certain pin (dynamically, whenever the user decides to)
  • a feature cannot be used unless handlePinMode() was called

I understand that this does not scale well. After your explanations, my understanding is now:

  • pin modes are something optional, primarily used by hardware-based features
  • there's no pre-defined method to enable or disable a feature
  • methods for initialization and destruction may be defined per feature (e.g. attach and detach in FirmataEncoder) and have to be called by the client accordingly

Did I get it right now?

Yes that sound right. It also makes me realize I should define a recommendation for use of enable/disable and/or attach/detach. Attach/detach is a common Arduino pattern.

Some features such as AccelStepperFirmata define enable/disable as a reflection of the enable/disable functionality of a motor driver board (see Stepper enable in the AccelStepperFirmata protocol definition). So one option would be to use enable/disable when hardware functionality is being enabled/disabled, whereas attach/detach would be used to attach or detach a firmware feature if/when it makes sense to do so (perhaps to temporarily or permanently ignore messages sent to or from a feature and free up or allocate memory if absolutely necessary).

An implementation (work in progress) can be found under RCSwitchFirmata/dev-2.0.0.

A couple of suggestions for your implementation:

  • Change IGNORE to PIN_MODE_IGNORE here and anywhere else it may be used.
  • Change MESSAGE to RCINPUT_MESSAGE here and where it's used to avoid compiler warnings in the event another library had used a define named "MESSAGE". My general recommendation is to prefix all command constants with the feature ID constant (RCINPUT_ in this particular case).

Thanks for your suggestions, I appreciate them and I'm looking forward to further comments.

I released the implementation as RCSwitchFirmata 2.0.0.

Great! I'll add it to firmatabuilder.

RCOutputFirmata and RCInputFirmata are now available as selections in the Contributed features section on firmatabuilder.com.