Commits

Craig Swank  committed 0797bf8 Merge

merged

  • Participants
  • Parent commits 827bbbf, 569b7eb

Comments (0)

Files changed (9)

File examples/blink.py

+from gadgets import get_gadgets, Addresses
+from gadgets.pins.beaglebone_black import pins
+
+arguments = {
+    'locations': {
+        'here': {
+            'led one': {
+                'type': 'switch',
+                'pin': pins['gpio'][9][16],
+            },
+        }
+    }
+}
+
+
+addresses = Addresses()
+gadgets = get_gadgets(arguments, addresses)
+gadgets.start()

File examples/brewery.py

 from gadgets import GadgetsFactory
-from gadgets.pins.beaglebone import pins
-
+from gadgets.pins.beaglebone_black import pins
+#NOTE on bbb the 1-wire pin is at p9.22
 args = {
     'locations': {
         'brewery': {
             'fan': {
                 'type':'switch',
-                'pin': pins['gpio'][8][17],
+                'pin': pins['gpio'][8][7],
             },
         },
         'hlt': {
             'valve': {
                 'type': 'valve',
-                'pin': pins['gpio'][8][11],
+                'pin': pins['gpio'][8][8],
                 'trigger': {
                     'type': 'float',
-                    'pin': pins['gpio'][8][12],
+                    'pin': pins['gpio'][8][9],
                     'volume': 26.5,
                 },
             },
             'heater': {
                 'type': 'electric heater',
-                'pin': pins['gpio'][8][25],
+                'pin': pins['pwm'][8][13],
             },
             'thermometer': {
                 'type': 'thermometer',
         'tun': {
             'valve': {
                 'type': 'valve',
-                'pin': pins['gpio'][8][14],
+                'pin': pins['gpio'][8][10],
                 'trigger': {
                     'type': 'gravity',
                     'source': 'hlt',
         'boiler': {
             'valve': {
                 'type': 'valve',
-                'pin': pins['gpio'][8][15],
+                'pin': pins['gpio'][8][11],
                 'trigger': {
                     'type': 'timer',
                     'source': 'tun',
             },
             'heater': {
                 'type': 'electric heater',
-                'pin': pins['gpio'][8][24],
+                'pin': pins['pwm'][8][19],
             },
             'cooler': {
                 'type': 'cooler',
-                'pin': pins['gpio'][8][22],
+                'pin': pins['gpio'][8][12],
             },
             'thermometer': {
                 'type': 'thermometer',
         'carboy': {
             'valve': {
                 'type': 'valve',
-                'pin': pins['gpio'][8][16],
+                'pin': pins['gpio'][8][14],
                 'trigger': {
                     'type': 'user',
                     'source': 'boiler',

File examples/recorder.py

 import pymongo
 import datetime
+import threading
 from gadgets import Gadgets, Addresses, Gadget
 
 
     def _register(self):
         pass
 
+
+    
+class Timer(threading.Thread):
+    """
+    If this timer is still valid after 30 minutes, something
+    must be wrong with the system.  Send an email
+    """
+
+    def __init__(self, event):
+        self.valid = True
+        self._event = event
+        super(Timer, self).__init__()
+
+    def run(self):
+        time.sleep(30 * 60)
+        if self.valid:
+            """
+            send and email
+            """
+            pass
+        
+
+class Alarm(Gadget):
+    """
+    In an aquaponics greenhouse the beds should fill up and then drain
+    every 15 minutes or so.  If something goes wrong I want to know,
+    or else fish, plants, or fish and plants will die.  
+    """
+
+    events = [
+        'bed one float_switch',
+        #'bed two float_switch',  #not using bed two right now
+        'bed three float_switch',
+        ]
+
+    def _start_timer(self, event):
+        t = Timer(event)
+        t.start()
+        self._timers[event] = t
+        
+    def on_start(self):
+        self._timers = {}
+        for event in self.events:
+            self._start_timer(event)
+        
+
+    def event_received(self, event, message):
+        t = self._timers.get(event)
+        if t:
+            t.valid = False
+            self._start_timer(event)
+            
+
+    def _register(self):
+        pass        
+
+    
 if __name__ == '__main__':
     location = 'greenhouse'
     addresses = Addresses(host=location) #configures this gadgets system as a remote, instead of the master

File gadgets/devices/heater/electric_heater.py

         return self._trigger_factory(self._on_event, self._off_event, message, target=None)
 
     def event_received(self, event, message):
-        print 'e r', event, message
         if event.startswith('update temperature'):
             self._update_pwm(message)
         else:
             super(ElectricHeater, self).event_received(event, message)
 
     def on(self, message):
-        print 'elec on'
         self._target_temperature = self._get_temperature(message)
         super(ElectricHeater, self).on(message)
 
                 value = (value * 1.8) + 32.0
             return value
 
-    @property
-    def io(self):
-        if self._io is None:
-            self._io = self._io_factory()
-            self._io.start()
-        return self._io
-
     def _update_pwm(self, message):
         if not self.io.status:
             return
         if self._location in message:
-            temperature = self._get_temperature(message[self._location]['input']['temperature'])
+            temperature = self._get_temperature(message[self._location]['input']['thermometer'])
             self.io.duty_percent = self._get_duty_percent(temperature)
 
     def _get_duty_percent(self, temperature):
             else:
                 duty_percent = 100
         return duty_percent
-
-
-        
-        

File gadgets/devices/heater/electric_heater_factory.py

-from gadgets.devices.heater.pwm import PWMFactory
+from gadgets.io import PWMFactory
 from gadgets.devices.heater.electric_heater import ElectricHeater
 
-def electric_heater_factory(location, name, arguments, addresses, io_factory=None, on=None, off=None):
+def electric_heater_factory(location, name, arguments, addresses, io_factory=None):
     if io_factory is None:
-        io_factory = PWMFactory(arguments['pin'])
+        io_factory = PWMFactory(arguments['pin'], frequency=1.0)
     return ElectricHeater(
         location,
         name,
         on=arguments.get('on'),
         off=arguments.get('off')
     )
-    

File gadgets/io/pwm.py

 
 class PWMFactory(object):
 
-    def __init__(self, pin, frequency=20000, mux_path='/sys/kernel/debug/omap_mux'):
+    def __init__(self, pin, frequency=1.0):
         self._pin = pin
         self._frequency = frequency
-        self._mux_path = mux_path
 
     def __call__(self):
-        return PWM(self._pin, self._frequency, self._mux_path)
+        return PWM(self._pin, frequency=self._frequency)
         
 
 class PWM(IO):
     NOTE:  The beaglebone pwm clock must be enabled before using this class.
     You can enable it by calling enable-pwm from the command line (requires
     gadgets and python-mmap to be installed)
+
+    # echo 20000000 > /sys/devices/ocp.3/pwm_test_P8_13.15/period
+
+    so  20000000= 0.02 seconds
+
+    # echo 10000000 > /sys/devices/ocp.3/pwm_test_P8_13.15/duty
+
+    so  10000000 = 0.01 seconds
     """
     
-    _mux = 'echo {0} > {1}/{2}'
-    _command = 'echo {0} > /sys/class/pwm/{1}/{2}'
+    _command_template = 'echo {0} > {1}/{2}'
+    _command_path_template = '/sys/devices/{0}'
 
-    def __init__(self, pin, frequency=20000, mux_path='/sys/kernel/debug/omap_mux'):
+    def __init__(self, pin, frequency=1.0):
         """
         mux:  the name that appears in the omap_mux directory
         directory: the directory for the pwm pin in /sys/class/pwm
         frequency:  the pwm frequency in Hz
         mux_path:  defaults to /sys/kernel/debug/omap_mux
         """
-        mux = pin['mux']
-        directory = pin['directory']
-        mode = pin['mode']
         self._current_value = None
-        self._directory = directory
-        os.system(self._mux.format(mode, mux_path, mux))
+        self._command = self._command_path_template.format(pin['directory'])
         self._write_value('run', '0')
-        self._write_value('duty_percent', '0')
-        self._write_value('period_freq', str(frequency))
+        frequency = int(1000000000 * frequency)
+        self._write_value('period', frequency)
         self._status = False
 
     @property
         """
         if self._current_value != value:
             self._current_value = value
-            self._write_value('run', '0')
-            self._write_value('duty_percent', value)
-            self._write_value('run', '1')
+            value = 1000000000 * (value / 100)
+            self._write_value('duty', value)
 
     def _write_value(self, path, value):
-        command = self._command.format(value, self._directory, path)
+        command = self._command_template.format(value, self._command, path)
         os.system(command)

File gadgets/pins/beaglebone_black.py

+"""
+In order to use these gpio pins
+it should be neccesary to disable
+htmi by editing uEnv.txt:
+
+  # mount /dev/mmcblk0p1  /mnt/card
+
+then edit /mnt/card/uEnv.txt so the
+optargs line looks like:
+
+optargs=quiet capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN
+
+  # umount /mnt/card
+  # shutdown -r now
+"""
+
 pins = {
     'adc': {
         9: {
     'pwm': {
         8: {
             13:{
-                'directory': 'ehrpwm.2:1',#ehrpwm2B
-                'mode':4
+                'directory': 'ocp.3/pwm_test_P8_13.12',
                 },
             19: {
-                'directory': 'ehrpwm.2:0',#ehrpwm2A
-                'mode':4
+                'directory': 'ocp.3/pwm_test_P8_19.13',
                 },
             },
         9: {
             14: {
                 'directory': 'ehrpwm.1:0', #ehrpwm1A_mux1
-                'mode': 6
             },
             16:{
                 'directory': 'ehrpwm.1:1',
-                'mode': 6
             },
             21:{
                 'directory': 'ehrpwm.0:1',
-                'mode': 3
             },
             22:{
                 'directory': 'ehrpwm.0:0',
-                'mode': 3
             },
         },
     },
     'gpio': {
         8: {
+            7: {
+                'export':66
+            },
+            8: {
+                'export':67
+            },
+            9: {
+                'export':69
+            },
             10: {
                 'export':68
             },
+            11: {
+                'export':45
+            },
+            12: {
+                'export':44
+            },
+            14: {
+                'export':26
+            },
+            15: {
+                'export':47
+            },
+            16: {
+                'export':46
+            },
             26:  {
                 'export':61
             },

File gadgets/tests/test_heater.py

 from nose.tools import eq_
 from gadgets import Gadgets, Addresses, Sockets, Broker
 from gadgets.devices import ElectricHeater, electric_heater_factory
-from gadgets.devices.heater.pwm import PWM
 
+path = '/private/tmp/electric_heater'
 port = random.randint(3000, 50000)
 
 
-class FakeGPIO(object):
+class FakePWM(object):
 
     def __init__(self):
-        self.addresses = Addresses(in_port=port, out_port=port+1, req_port=port+2)
+        self.addresses = Addresses(in_port=port, out_port=port+1)
         self.sockets = Sockets(self.addresses)
         self.status = False
-        self.closed = False
+        self._duty_percent = 100
+
+    def write(self, msg):
+        with open(path, 'w') as f:
+            f.write(msg)
+        self.sockets.send('test update')
 
     def on(self):
-        print "turning on"
+        self.write('on {0}%'.format(self._duty_percent))
         self.status = True
 
     def off(self):
-        print "turning off"
-        self.sockets.send('test pwm off')
+        self.write('off')
         self.status = False
+        time.sleep(0.3)
+        self.sockets.close()
 
     def close(self):
         self.sockets.close()
-        self.closed = True
-        
-def get_fake_gpio():
-    return FakeGPIO()
 
-def get_pwm(*args, **kw):
-    return PWM(get_fake_gpio)
+    @property
+    def duty_percent(self):
+        pass
+
+    @duty_percent.setter
+    def duty_percent(self, value):
+        self._duty_percent = value
+        self.on()
+
+
+def get_fake_pwm(*args, **kw):
+    return FakePWM()
 
-    
 class TestHeater(object):
 
     def setup(self):
-        self.addresses = Addresses(in_port=port, out_port=port+1, req_port=port+2)
-        self.sockets = Sockets(self.addresses, events=['test pwm off'])
         
+        self.addresses = Addresses(in_port=port, out_port=port+1)
+        self.sockets = Sockets(self.addresses, events=['test update'])
+        ElectricHeater._pwm_factory = get_fake_pwm
         self.heater = ElectricHeater(
             'living room',
             'heater',
             self.addresses,
-            io_factory=get_pwm,
+            io_factory=get_fake_pwm,
         )
         self.gadgets = Gadgets([self.heater], self.addresses)
 
+    def teardown(self):
+        self.sockets.send('shutdown')
+        time.sleep(0.2)
+        self.sockets.close()
+        
     def test_create(self):
         pass
 
             return f.read()
 
     def test_on_and_off(self):
-        """
-        hard to test, try later when brain is smarter
-        """
-        pass
-        # t = threading.Thread(target=self.gadgets.start)
-        # t.start()
-        # time.sleep(1)
-        # self.sockets.send('heat living room', {'units': 'C', 'value': 88})
-        # event, message = self.sockets.recv()
-        # eq_(event, 'test pwm off')
-        # eq_(self.heater.io.duty_percent, 100)
-        # self.sockets.send('update temperature', {'living room': {'input': {'temperature': {'value': 87, 'units': 'C'}}}})
-        # event, message = self.sockets.recv()
-        # eq_(event, 'test pwm off')
-        # eq_(self.heater.io.duty_percent, 25)
-        # self.sockets.send('update temperature', {'living room': {'input': {'temperature': {'value': 88, 'units': 'C'}}}})
-        # event, message = self.sockets.recv()
-        # eq_(event, 'test pwm off')
-        # eq_(self.heater.io.duty_percent, 0)
-        # time.sleep(1)
-        # self.sockets.send('shutdown')
-        # time.sleep(0.2)
-        # self.sockets.close()
+        t = threading.Thread(target=self.gadgets.start)
+        t.start()
+        time.sleep(1)
+        self.sockets.send('heat living room', {'units': 'C', 'value': 88})
+        self.sockets.recv()
+        eq_(self._read(), 'on 100%')
+        self.sockets.send('update temperature', {'living room': {'input': {'thermometer': {'value': 87, 'units': 'C'}}}})
+        self.sockets.recv()
+        eq_(self._read(), 'on 25%')
+        self.sockets.send('update temperature', {'living room': {'input': {'thermometer': {'value': 88, 'units': 'C'}}}})
+        self.sockets.recv()
+        eq_(self._read(), 'on 0%')
+        time.sleep(1)

File gadgets/tests/test_heater_pwm.py

-from nose.tools import eq_
-from gadgets.devices.heater.pwm import PWM
-
-path = '/tmp/switch'
-
-class FakeGPIO(object):
-
-    def __init__(self):
-        self.status = False
-        self.closed = False
-
-    def on(self):
-        with open(path, 'w') as f:
-            f.write('on')
-        self.status = True
-
-    def off(self):
-        with open(path, 'w') as f:
-            f.write('off')
-        self.status = False
-
-    def close(self):
-        self.closed = True
-
-def get_fake_gpio():
-    return FakeGPIO()
-
-class TestHeaterPWM(object):
-
-    def setup(self):
-        self.pwm = PWM(get_fake_gpio)
-        
-    def test_create(self):
-        pass
-
-    def test_close(self):
-        self.pwm.close()
-        assert self.pwm.gpio.closed
-
-    def test_duty_percent(self):
-        self.pwm.duty_percent = 50
-        eq_(self.pwm._on_time, 5.0)
-        eq_(self.pwm._off_time, 5.0)
-
-        self.pwm.duty_percent = 25
-        eq_(self.pwm._on_time, 2.5)
-        eq_(self.pwm._off_time, 7.5)
-
-        self.pwm.duty_percent = 75
-        eq_(self.pwm._on_time, 7.5)
-        eq_(self.pwm._off_time, 2.5)
-
-        self.pwm.duty_percent = 0
-        eq_(self.pwm._on_time, 0.0)
-        eq_(self.pwm._off_time, 10.0)
-
-        self.pwm.duty_percent = 100
-        eq_(self.pwm._on_time, 10.0)
-        eq_(self.pwm._off_time, 0.0)