ZigSnake

Spencer Russell

@ssfrr

http://ssfrr.com

Overview

ZigBee Overview

unittest

ZigSnake Overview

ZigSnake Internals

Live Demo

ZigBee Overview

ZigBee Cluster Library (ZCL)

Clusters

Client/Server Model

Commands

Attributes

unittest

TestCase Class

Assertions

import unittest
from widget import Widget

class WidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

    def tearDown(self):
        self.widget.dispose()
        self.widget = None

    def test_default_size(self):
        self.assertEqual(self.widget.size(), (50,50),
                         'incorrect default size')

    def test_resize(self):
        self.widget.resize(100,150)
        self.assertEqual(self.widget.size(), (100,150),
                         'wrong size after resize')
if __name__ == '__main__':
    unittest.main()
                

ZigSnake Overview

from zcl import ZCL
from zigbee import ZBController
import unittest
                
class LevelControlTestCase(unittest.TestCase):
    def setUp(self):
        z = ZCL(['general.xml', 'ha.xml',
                 'ha12.xml', 'ota.xml'])
        con = ZBController()
        con.open(192.168.1.134)
        con.enable_permit_join()
        device_id = con.wait_for_join()
        con.disable_permit_join()
                
    def test_move_to_level_updates_attribute(self):
        desired_level = 127
        con.send_zcl_command(
                device_id,
                z.level_control.move_to_level(
                        desired_level, 0))
        level = con.read_attribute(
                device_id, z.level_control.current_level)
        self.assertEqual(level, desired_level)
                
class TestBasicFunctionality(DoorLockTestCase):
    def test_unlock(self):
        raw_input("Make sure lock is locked. Press Enter")
        conn.send_zcl_command(z.door_lock.unlock_door(''))
        conn.expect_zcl_command(
                z.door_lock.unlock_door_response(success))
        self.assertConfirm("Did the bolt unlock?")
                

ZigSnake Internals

  <cluster>
    <name>Level Control</name>
    <code>0x0008</code>
                
    <attribute side="server" code="0x0000"
        type="INT8U">current level</attribute>
    <attribute side="server" code="0x0001"
        type="INT16U">remaining time</attribute>
                
    <command source="client" code="0x00" name="MoveToLevel">
      <arg name="level"          type="INT8U"/>
      <arg name="transitionTime" type="INT16U"/>
    </command>
  </cluster>
                
import elementtree.ElementTree
class ZCL:
    def __init__(self, xml_files = None):
        if not xml_files:
            return
        for xml_file in xml_files:
            tree = xml.parse(xml_file)
            root = tree.getroot()
            for cluster_xml in root.iter('cluster'):
                setattr(self, _attr_from_name(
                        cluster_xml.find('name').text),
                        ZCLCluster(cluster_xml))
class ZCLCluster:
    def __init__(self, cluster_xml):
        self.name = cluster_xml.find('name').text
        self.define = cluster_xml.find('define').text
        self.code = int(cluster_xml.find('code').text, 0)
        self.add_commands(cluster_xml)
        self.add_attributes(cluster_xml)

    def add_commands(self, cluster_xml):
        for cmd_xml in cluster_xml.findall('command'):
            setattr(self,
                    _attr_from_name(cmd_xml.get('name')),
                    ZCLCommandPrototype(self.code, cmd_xml))

    def add_attributes(self, cluster_xml):
        for attr_xml in cluster_xml.findall('attribute'):
            setattr(self,
                    _attr_from_name(attr_xml.text),
                    ZCLAttribute(self.code, attr_xml))
                

Live Demo

Spencer Russell

github.com/bulogics/zigsnake

@ssfrr ssfrr.com @bulogics bulogics.com