gozw

package module
v0.0.0-...-c4a4cf6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2020 License: MIT Imports: 25 Imported by: 5

README

Fork of https://gitlab.com/helioslabs/gozw and https://gitlab.com/helioslabs/zwgen.

Working with the authors of https://github.com/stampzilla/gozwave and https://gitlab.com/helioslabs/gozw to create a unified Z-Wave library for Go. Currently a work in progress.

Join the #gozwave channel on the Gophers slack.

gozw

Golang Z/IP Portal

Getting Started

  1. You need a Z-Wave USB bridge controller with Serial API >= 4.05
  2. With the controller plugged in, if you do not see a device in /dev named usbserial* or usbmodem* (or similar), you need to install the FTDI VCP driver for your platform
  3. OPTIONAL: Install interceptty, which is an extremely useful serial port / tty proxy (it will allow you to see the raw data being transmitted to/from the controller).
  • Installation is as simple as ./configure && make && sudo cp interceptty /usr/local/bin
  • To run: interceptty -s 'ispeed 115200 ospeed 115200' /dev/<serialdevice> /tmp/<serialdevice>
  • Be sure to update your config.yaml to point to /tmp/<serialdevice>
  1. go get -u github.com/gozwave/zwgen
  2. make install-deps in the zwgen folder root
  3. make install in the zwgen folder root
  4. make build in the zwgen folder
  5. go get ./... in the gozw folder root
  6. go generate ./... in the gozw folder root
  7. go run cmd/portald/main.go
  8. go run cmd/gatewayd/main.go

Summary

  1. Transport layer - handles raw communication with the Z-Wave controller via serial port
  2. Frame layer - handles frame encoding/decoding to/from binary
  3. Frame parser - parses frames by implementing the finite state machine defined in INS12350 section 6.6.1
  4. Session Layer - handles frame sequencing and host media access control
  5. Serial API Layer - defines Z-Wave API functions (as described in INS12308) and handles requests, responses, and callbacks
  6. Application Layer - tracks network data, node information, security information, etc
  7. Security Layer - provides utilities for encrypting/decrypting secure messages
Application Layer   < ---- >   Security layer
       |
       V
 Serial API Layer
       |
       V
  Session Layer
       |
       V
   Frame Layer      < ---- >   Frame parser
       |
       V
 Transport Layer

Layers

Transport Layer

Handles reads/writes with the serial port. In the case of future implementations that do not use a USB-UART driver, it should be possible to substitute an implementation for some other I/O device (UART/SPI/etc).

It satisfies several interfaces from the io package. In the future, it should be possible to dump a long-running Z-Wave interaction (output from interceptty, for example) to a file, then use that file as input to reproduce crashes.

Responsibilities
  • Read/write bytes to/from an I/O source (serial port, file, network, etc.)
Frame Layer

Parses incoming frames using the frame parser and determines how to proceed based on the parser result. Handles parse/receive timeouts, as well as transmission of ACKs/NAKs.

Responsibilities
  • Encode frames to raw bytes and write them to the transport layer
  • Read bytes from the transport layer and send them to the frame parser
  • Perform basic locking to prevent transmitting frames while in the process of receiving frames
    • Note: because this layer does not have any knowledge of Z-Wave API functions, it will not perform any locking with regard to the REQ/RES flow
  • ACK valid frames (based on the frame checksum)
  • NAK invalid frames (based on the frame checksum)
  • TODO: Handle ACK timeouts
  • TODO: Handle transmit/receive collisions
  • TODO: Handle CAN frames
  • TODO: Handle retransmission and backoff
Session Layer

Facilitates the request/response flow by queueing requests when awaiting responses and callbacks. Implements the Host Request/Response Session state machine as described in INS12350 section 6.6.3.

Responsibilities
  • Locking to prevent request concurrency
  • Routing and matching of responses and callbacks to the appropriate handlers
  • Routing of unsolicited commands (usually from ApplicationControllerUpdate) to the application layer
Serial API Layer

Exposes an API to make Z-Wave function calls (such as AddNodeToNetwork and SendData).

Whenever possible, methods exposed by this layer should block until their corresponding Z-Wave operation has completed (e.g. AddNodeToNetwork, which has a complex workflow consisting of multiple callback functions, should block until the entire process has concluded, and return the newly added node or an error).

Responsibilities
  • Implementation of Serial API functions
Application Layer

The application layer abstracts the Z-Wave protocol so that user implementations do not need an in-depth understanding of Serial API functions or command classes. It manages the network at a high level by keeping track of nodes, acting as a proxy to the session layer, and receiving data frames (typically command classes whether GETs or REPORTs) from the session layer.

Responsibilities
  • Network management
  • Node information tracking
  • Handling of security command classes (via the Security Layer)
Security Layer

For background, see SDS10865 (yep, the whole document; it's not that long).

Provides utilities for encrypting/decrypting messages, storing and timing out nonces, and security sequence counters.

Responsibilities
  • Generating internal nonces in response to nonce challenges from other nodes
  • Fetching nonces from other secure nodes
  • Mangaging nonce timers and usage (they are short-lived and can only be used once)
  • Encrypting outgoing message payloads (and creating HMACs)
  • Sequencing (splitting) of outgoing message payloads when necessary
  • Decrypting incoming message paylods (and verifying HMACs)
  • Reassembly of sequenced incoming messages

Resources

  1. INS12308 - Z-Wave 500 Series Application Programming Guide (v6.51.06)
  2. INS12350 - Serial API Host Application Programming Guide
  3. SDS10865 - Z-Wave Application Security Layer
  4. http://pepper1.net/zwavedb/ Random Z-Wave device library (lots of technical info)

Documentation

Index

Constants

View Source
const (
	SecurePayloadMaxSizeExplore   = 26 // in bytes
	SecurePayloadMaxSizeAutoRoute = 28
	SecurePayloadMaxSizeNoRoute   = 34
)

Maximum possible size (in bytes) of the plaintext payload to be sent when sending a secure frame, based on the SendData options. The smallest possible must be used based on the given option bitset (e.g. if using both no route and explore, the maximum size is 26).

View Source
const MaxSecureInclusionDuration = time.Second * 60

MaxSecureInclusionDuration is the timeout for secure inclusion mode. If this timeout expires, secure inclusion will be canceled no matter how far the process has proceeded.

Variables

This section is empty.

Functions

func DefaultEventCallback

func DefaultEventCallback(c *Client, nodeID byte, e cc.Command)

DefaultEventCallback is the default callback for handling events.

func NewLogger

func NewLogger() (*zap.Logger, error)

NewLogger builds a new logger.

Types

type Client

type Client struct {
	Controller Controller

	// REPLACE THIS WITH A GENERIC CALLBACK FUNCTION
	// EventBus EventBus.Bus
	EventCallback func(*Client, byte, cc.Command)
	// contains filtered or unexported fields
}

func NewDefaultClient

func NewDefaultClient(dbName, serialPort string, baudRate int, networkKey []byte) (*Client, error)

func (*Client) AddNode

func (c *Client) AddNode() (*Node, error)

func (*Client) Node

func (c *Client) Node(nodeID byte) (*Node, error)

Node will retrieve a single node.

func (*Client) Nodes

func (c *Client) Nodes() map[byte]*Node

Nodes will return all nodes

func (*Client) RemoveFailedNode

func (c *Client) RemoveFailedNode(nodeID byte) (ok bool, err error)

func (*Client) RemoveNode

func (c *Client) RemoveNode() (byte, error)

func (*Client) SendData

func (c *Client) SendData(dstNode byte, payload encoding.BinaryMarshaler) error

func (*Client) SendDataSecure

func (c *Client) SendDataSecure(dstNode byte, message encoding.BinaryMarshaler) error

SendDataSecure encapsulates payload in a security encapsulation command and sends it to the destination node.

func (*Client) SetEventCallback

func (c *Client) SetEventCallback(callback func(c *Client, nodeID byte, e cc.Command))

SetEventCallback will set the event callback for any events received

func (*Client) SetLogger

func (c *Client) SetLogger(logger *zap.Logger)

func (*Client) Shutdown

func (c *Client) Shutdown() error

Shutdown will stop the client.

type Controller

type Controller struct {
	APIVersion          string `json:"apiversion"`
	APILibraryType      string `json:"apilibrary_type"`
	HomeID              uint32 `json:"home_id"`
	NodeID              byte   `json:"node_id"`
	Version             byte   `json:"version"`
	APIType             string `json:"apitype"`
	IsPrimaryController bool   `json:"is_primary_controller"`
	ApplicationVersion  byte   `json:"application_version"`
	ApplicationRevision byte   `json:"application_revision"`
	SupportedFunctions  []byte `json:"supported_functions"`
	NodeList            []byte `json:"node_list"`
}

Controller contains information for the controller.

type Node

type Node struct {
	NodeID byte

	Capability          byte
	BasicDeviceClass    byte
	GenericDeviceClass  byte
	SpecificDeviceClass byte

	Failing bool

	CommandClasses cc.CommandClassSet

	NetworkKeySent bool

	ManufacturerID uint16
	ProductTypeID  uint16
	ProductID      uint16

	QueryStageSecurity     bool
	QueryStageManufacturer bool
	QueryStageVersions     bool
	// contains filtered or unexported fields
}

func NewNode

func NewNode(client *Client, nodeID byte) (*Node, error)

func (*Node) AddAssociation

func (n *Node) AddAssociation(groupID byte, nodeIDs ...byte) error

func (*Node) GetBasicDeviceClassName

func (n *Node) GetBasicDeviceClassName() string

func (*Node) GetGenericDeviceClassName

func (n *Node) GetGenericDeviceClassName() string

func (*Node) GetSpecificDeviceClassName

func (n *Node) GetSpecificDeviceClassName() string

func (*Node) GetSupportedCommandClassStrings

func (n *Node) GetSupportedCommandClassStrings() []string

func (*Node) GetSupportedSecureCommandClassStrings

func (n *Node) GetSupportedSecureCommandClassStrings() []string

func (*Node) IsListening

func (n *Node) IsListening() bool

func (*Node) IsSecure

func (n *Node) IsSecure() bool

func (*Node) LoadCommandClassVersions

func (n *Node) LoadCommandClassVersions() error

func (*Node) LoadManufacturerInfo

func (n *Node) LoadManufacturerInfo() error

func (*Node) LoadSupportedSecurityCommands

func (n *Node) LoadSupportedSecurityCommands() error

func (*Node) RequestNodeInformationFrame

func (n *Node) RequestNodeInformationFrame() error

func (*Node) SendCommand

func (n *Node) SendCommand(command cc.Command) error

func (*Node) SendRawCommand

func (n *Node) SendRawCommand(payload []byte) error

func (*Node) String

func (n *Node) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL