rockwood / exbee

Communicate with XBee wireless radios in Elixir
https://hex.pm/packages/exbee
Other
6 stars 4 forks source link

Digimesh support #3

Closed nlevnaut closed 5 years ago

nlevnaut commented 6 years ago

Feature request

Digimesh is not used as much as Zigbee, but it has some nice features and Digi has some long-range modules that use it. It would be very nice to have support for multiple XBee protocols built into exbee.

Zigbee VS Digimesh

XBee-PRO 2.4GHz Digimesh User Guide

XBee-PRO 900HP and XSC RF Modules User Guide

I believe their 900MHz and 2.4GHz modules have the same API mode... not 100% though.

I have a C implementation I've tested with their 900MHz modules on an ATMega328p here: atmega-xbee-digimesh. Most of the relevant stuff to look at for this project is in xbee.c and xbee.h. It's a bit bare-bones but API mode rx and tx both work.

rockwood commented 6 years ago

I think this should pretty easy to get working without needing any changes to Exbee. It looks like the digimesh and zigbee protocols are identical with just a different addressing scheme. Let's take the Transmit Request frame - 0x10 as an example. The Exbee.TxFrame has a network address and mac address. A digimesh compatible frame would have only a mac address.

defmodule MyDigiMeshTxFrame do
  defstruct [id: 0x01, mac_addr: 0x000000000000FFFF, radius: 0x00, options: 0x00, payload: nil]

  defimpl Exbee.EncodableFrame do
    alias Exbee.Util

    def encode(%{id: id, mac_addr: mac_addr, radius: radius, options: options, payload: payload}) do
      binary_payload = Util.to_binary(payload)
      <<0x10, id::8, mac_addr::64, 0xFFFE, radius::8, options::8, binary_payload::binary>>
    end
  end
end

And to use it:

iex> {:ok, pid} = Exbee.start_link(serial_port: "COM1", speed: 9600)
iex> Exbee.send_frame(pid, %MyDigiMeshTxFrame{mac_addr: ..., payload: ...})
:ok

I'd happily merge a PR that adds digimesh specific frames to Exbee.

nlevnaut commented 6 years ago

Ok, cool. I'm about halfway through the getting-started guide, but I've fallen down the Elixir rabbit hole and I'll look into adding Digimesh frames. :)

rockwood commented 6 years ago

@liberza I totally know the feeling. I started down the Elixir path a couple years ago and haven't looked back. It's a fantastic language, and I think you'll be very happy with it.

Let me know if you have any questions along the way. I'm @rockwood on Elixir Slack.

nlevnaut commented 6 years ago

I've added a new frame, Exbee.DigiMeshTxFrame. I only have one USB/serial adapter to test with at the moment, so I also created Exbee.DigiMeshTxResultFrame to test that TX works. I noticed I was never receiving the DigiMesh TX result, so I looked into Exbee.Message.

The DigiMesh TX result frame is slightly different than the ZigBee one, in that there are 2 reserved bytes after the frame ID in DigiMesh. They have the same frame ID though, which may make things interesting. I see in Exbee.Message, the decodable frames are mapped by ID.

I'm thinking that perhaps the IDs in @decodable_frames could map to tuples containing the different "flavors" of frame that use that ID. Like this:

@decodable_frames %{
    0x88 => {Exbee.ATCommandResultFrame},
    0x8A => {Exbee.DeviceStatusFrame, Exbee.DigiMeshDeviceStatusFrame},
    0x8B => {Exbee.TxResultFrame, Exbee.DigiMeshTxResultFrame},
    0x90 => {Exbee.RxFrame, Exbee.DigiMeshRxFrame},
    0x91 => {Exbee.ExplicitRxFrame, Exbee.DigiMeshExplicitRxFrame},
    0x92 => {Exbee.RxSampleReadFrame},
    0x94 => {Exbee.RxSensorReadFrame},
    0x97 => {Exbee.RemoteATCommandResultFrame},
  }

Then just attempt decoding a frame with each frame type in the tuple, until the end or until one works.

The other way I thought of doing it is by just requiring the user to specify that they are using DigiMesh, and only attempt decoding DigiMesh frames in that case.

nlevnaut commented 6 years ago

Wait. Something smells here. The reserved portion of the DigiMesh frames is the same spot that the network address would be in ZigBee frames. Your default network_addr is 0xFFFE, so using Exbee.TxFrame without a network_addr specified should give us a DigiMesh frame.

Same with the TxResultFrame. The Digi documentation for the 900HP appears to have a typo in their table that is a bit misleading.

So... exbee should already support DigiMesh frames! I can test once I receive my new USB/serial adapter.

rockwood commented 6 years ago

@liberza Yeah, I guess that would make sense if they both use the same frame type identifier. I assume they anticipated a network having both Xbee and Digimesh modules. Let me know if that works when you find out more.

nlevnaut commented 6 years ago

Looks like it sort-of works! I had some weird settings on my XBees from a while back, but I reset them to factory mode and TxFrame appears to be compatible. TxResultFrame is received intact as well. The checksum seems to fail for receive though. I'll dig into that.

rockwood commented 6 years ago

@liberza Great! Yeah, my use case for creating Exbee was pretty limited so I haven't thoroughly tested every frame type. Please send me a PR if you find any problems.

rockwood commented 5 years ago

Closing for now