Exemplo n.º 1
0
    def startInputs(self, global_data):
        ''' Start Home Monitor Input routines '''

        input_queue = global_data[Constants.GlobalData.INPUT_QUEUE]
        self.input = ProcessInput(input_queue)

        # Start thread for inputing data
        if (not self.options.in_test_mode):
            self.logger.debug('Starting xbee input')
            self.xbee_thread = XBeeInputThread(input_queue)
            self.xbee_thread.start()

        # The following will test various inputs
        if (self.options.in_test_mode):
            self.logger.debug('Starting test thread')
            self.test_input = TestInputThread(input_queue)
            self.test_input.start()

        self.logger.debug('Starting scheduler')
        self.sched = HMScheduler(input_queue)
        self.sched.start()

        if (sys.platform[:5] == 'linux' and not self.options.in_test_mode):
            self.logger.debug('Starting ComputerMonitor')
            self.computer_monitor = ComputerMonitor(input_queue)
            self.computer_monitor.start()
 def test_ProcessInput_work_status_request( self, process, config, receive ):
     envelope = DataEnvelope( Constants.EnvelopeTypes.STATUS )
     que = HMQueue()
     pi = ProcessInput( que )
     que.receive.return_value = envelope
     pi.work()
     que.receive.assert_called_oncy_with()
     pi.commands[envelope.type].process.assert_called_once_with( envelope )
Exemplo n.º 3
0
 def test_ProcessInput_work_status_request(self, process, config, receive):
     envelope = DataEnvelope(Constants.EnvelopeTypes.STATUS)
     que = HMQueue()
     pi = ProcessInput(que)
     que.receive.return_value = envelope
     pi.work()
     que.receive.assert_called_oncy_with()
     pi.commands[envelope.type].process.assert_called_once_with(envelope)
Exemplo n.º 4
0
    def startInputs( self, global_data ):
        ''' Start Home Monitor Input routines '''

        input_queue = global_data[Constants.GlobalData.INPUT_QUEUE]
        self.input = ProcessInput( input_queue )

        # Start thread for inputing data
        if ( not self.options.in_test_mode ):
            self.logger.debug( 'Starting xbee input' )
            self.xbee_thread = XBeeInputThread( input_queue )
            self.xbee_thread.start()

        # The following will test various inputs
        if ( self.options.in_test_mode ):
            self.logger.debug( 'Starting test thread' )
            self.test_input = TestInputThread( input_queue )
            self.test_input.start()

        self.logger.debug( 'Starting scheduler' )
        self.sched = HMScheduler( input_queue )
        self.sched.start()

        if ( sys.platform[:5] == 'linux' and
            not self.options.in_test_mode ):
            self.logger.debug( 'Starting ComputerMonitor' )
            self.computer_monitor = ComputerMonitor( input_queue )
            self.computer_monitor.start()
 def test_input( self, receive, work, config ):
     que = HMQueue()
     self.pi = ProcessInput( que )
     work.side_effect = self.side_effect
     self.pi.input()
     self.pi.work.assert_called_once_with()
class Test( unittest.TestCase ):
    logger = logging.getLogger( 'UnitTest' )

    valid_devices_configuration = {'0x13a200408cccc3': {'adc-0': {'cosm_channel': '3',
                                   'description': 'The temperature in the sunroom',
                                   'name': 'Indoor Temperature',
                                   'steps': ['step.ZigbeeAnalogNumberToVolts',
                                             'step.TMP_36_Volts_to_Centigrade',
                                             'step.Centigrade_to_Fahrenheit',
                                             'step.Average',
                                             'step.FormatValue',
                                             'step.CurrentValue'],
                                   'units': 'F'},
                         'adc-1': {'cosm_channel': '3',
                                   'description': 'The temperature at 100 West Lisa Drive Austin TX',
                                   'name': 'Outdoor Temperature',
                                   'steps': ['step.ZigbeeAnalogNumberToVolts',
                                             'step.TMP_36_Volts_to_Centigrade',
                                             'step.Centigrade_to_Fahrenheit',
                                             'step.Average',
                                             'step.FormatValue',
                                             'step.CurrentValue'],
                                   'units': 'F'},
                         'name': 'Sunroom',
                         'network_address': '0xf9f2'},
    '0x13a200409029bf': {'adc-1': {'cosm_channel': '2',
                                   'description': 'The temperature above the garage door',
                                   'name': 'Garage Temperature',
                                   'steps': ['step.ZigbeeAnalogNumberToVolts',
                                             'step.TMP_36_Volts_to_Centigrade',
                                             'step.Centigrade_to_Fahrenheit',
                                             'step.Average',
                                             'step.FormatValue',
                                             'step.CurrentValue',
                                             'step.oneInN',
                                             'outputs.COSM'],
                                   'units': 'F'},
                         'dio-0': {'cosm_channel': '1',
                                   'description': 'Monitors whether the garage door is open or closed.',
                                   'name': 'Garage Door Monitor',
                                   'network_address': '0xf9f2',
                                   'steps': ['step.garage_door_state',
                                             'step.CurrentValue',
                                             'step.onBooleanChange',
                                             'outputs.COSM']},
                         'name': 'Garage Door XBee Monitor',
                         'network_address': '0xf9f2'}}

    def setUp( self ):
        logging.config.fileConfig( "unittest_logging.conf" )

    def tearDown( self ):
        pass

# ProcessXBeeInput

    def test_ProcessXBeeInput_logger_name( self ):
        devices = {'device': {'port': {}}}
        pxi = ProcessXBeeInput( devices )
        self.assertEqual( pxi.logger_name, Constants.LogKeys.inputsZigBee )

    @patch( 'housemonitor.inputs.processinput.Common.send' )
    @patch( 'housemonitor.inputs.processinput.xmlDeviceConfiguration.configure' )
    def test_XBeeInput_process_invalid_device_error( self, config, send ):
        data = {'source_addr_long': '\x00\x13\xa2\x00@\x90)\xbf',
                       'source_addr': '\xf9\xf2',
                        'id': 'rx_io_data_long_addr',
                         'samples': [{'adc-1': 622}],
                       'options': '\x01'}
        env = DataEnvelope( Constants.EnvelopeTypes.XBEE, **data )

        xd = xmlDeviceConfiguration()
        xd.devices = {'0x13a200408cccc3': {'adc-0': {'cosm_channel': '3',
                                   'description': 'The temperature in the sunroom',
                                   'name': 'Indoor Temperature',
                                   'steps': ['step.ZigbeeAnalogNumberToVolts',
                                             'step.TMP_36_Volts_to_Centigrade',
                                             'step.Centigrade_to_Fahrenheit',
                                             'step.Average',
                                             'step.FormatValue',
                                             'step.CurrentValue'],
                                   'units': 'F'},
                         'adc-1': {'cosm_channel': '3',
                                   'description': 'The temperature at 100 West Lisa Drive Austin TX',
                                   'name': 'Outdoor Temperature',
                                   'steps': ['step.ZigbeeAnalogNumberToVolts',
                                             'step.TMP_36_Volts_to_Centigrade',
                                             'step.Centigrade_to_Fahrenheit',
                                             'step.Average',
                                             'step.FormatValue',
                                             'step.CurrentValue'],
                                   'units': 'F'},
                         'name': 'Sunroom',
                         'network_address': '0xf9f2'}}

        xp = ProcessXBeeInput( xd )
        xp.logger.exception = MagicMock()
        value = xp.process( env )
        xp.logger.exception.assert_called_with( "'Invalid device (0x13a200409029bf)'" )
        self.assertEqual( send.call_count, 0 )

    @patch( 'housemonitor.inputs.processinput.Common.send' )
    @patch( 'housemonitor.inputs.processinput.xmlDeviceConfiguration.configure' )
    def test_XBeeInput_process_invalid_port_error( self, config, send ):

        data = {'source_addr_long': '\x00\x13\xa2\x00@\x90)\xbf',
                       'source_addr': '\xf9\xf2',
                        'id': 'rx_io_data_long_addr',
                         'samples': [{'adc-3': 622}],
                       'options': '\x01'}
        env = DataEnvelope( Constants.EnvelopeTypes.XBEE, **data )

        xd = xmlDeviceConfiguration()
        xd.devices = {'0x13a200409029bf': {'adc-0': {'cosm_channel': '3',
                                   'description': 'The temperature in the sunroom',
                                   'name': 'Indoor Temperature',
                                   'steps': ['step.ZigbeeAnalogNumberToVolts',
                                             'step.TMP_36_Volts_to_Centigrade',
                                             'step.Centigrade_to_Fahrenheit',
                                             'step.Average',
                                             'step.FormatValue',
                                             'step.CurrentValue'],
                                   'units': 'F'},
                         'adc-1': {'cosm_channel': '3',
                                   'description': 'The temperature at 100 West Lisa Drive Austin TX',
                                   'name': 'Outdoor Temperature',
                                   'steps': ['step.ZigbeeAnalogNumberToVolts',
                                             'step.TMP_36_Volts_to_Centigrade',
                                             'step.Centigrade_to_Fahrenheit',
                                             'step.Average',
                                             'step.FormatValue',
                                             'step.CurrentValue'],
                                   'units': 'F'},
                         'name': 'Sunroom',
                         'network_address': '0xf9f2'}}

        xp = ProcessXBeeInput( xd )
        xp.logger.exception = MagicMock()
        value = xp.process( env )
        xp.logger.exception.assert_called_with( "'Invalid port (adc-3)'" )
        self.assertEqual( send.call_count, 0 )

    @patch( 'housemonitor.inputs.processinput.Common.send' )
    @patch( 'housemonitor.inputs.processinput.xmlDeviceConfiguration.configure' )
    def test_XBeeInput_process_invalid_configuration_options_error( self, config, send ):

        data = {'source_addr_long': '\x00\x13\xa2\x00@\x90)\xbf',
                       'source_addr': '\xf9\xf2',
                        'id': 'rx_io_data_long_addr',
                         'samples': [{'adc-0': 622}],
                       'options': '\x01'}
        env = DataEnvelope( Constants.EnvelopeTypes.XBEE, **data )

        xd = xmlDeviceConfiguration()
        xd.devices = {'0x13a200409029bf': {'adc-0': {'cosm_channel': '3',
                                   'description': 'The temperature in the sunroom',
                                   'name': 'Indoor Temperature',
                                   'steps': ['step.ZigbeeAnalogNumberToVolts',
                                             'step.TMP_36_Volts_to_Centigrade',
                                             'step.Centigrade_to_Fahrenheit',
                                             'step.Average',
                                             'step.FormatValue',
                                             'step.CurrentValue']},
                         'adc-1': {'cosm_channel': '3',
                                   'description': 'The temperature at 100 West Lisa Drive Austin TX',
                                   'name': 'Outdoor Temperature',
                                   'steps': ['step.ZigbeeAnalogNumberToVolts',
                                             'step.TMP_36_Volts_to_Centigrade',
                                             'step.Centigrade_to_Fahrenheit',
                                             'step.Average',
                                             'step.FormatValue',
                                             'step.CurrentValue'],
                                   'units': 'F'},
                         'name': 'Sunroom',
                         'network_address': '0xf9f2'}}

        xp = ProcessXBeeInput( xd )
        xp.logger.exception = MagicMock()
        value = xp.process( env )
        xp.logger.exception.assert_called_with( "'Required configuration option not present (units) for device(0x13a200409029bf) port (adc-0)'" )
        self.assertEqual( send.call_count, 0 )

    @patch( 'housemonitor.inputs.processinput.datetime' )
    @patch( 'housemonitor.inputs.processinput.Common.send' )
    @patch( 'housemonitor.inputs.processinput.xmlDeviceConfiguration.configure' )
    def test_XBeeInput_process_with_valid_data( self, config, send, dt ):
        test_time = datetime.datetime( 2012, 1, 2, 3, 4, 5 )
        data = {'source_addr_long': '\x00\x13\xa2\x00@\x90)\xbf',
                       'source_addr': '\xf9\xf2',
                        'id': 'rx_io_data_long_addr',
                         'samples': [{'adc-1': 622}],
                       'options': '\x01'}
        env = DataEnvelope( Constants.EnvelopeTypes.XBEE, **data )

        xd = xmlDeviceConfiguration()
        xd.devices = self.valid_devices_configuration
        xp = ProcessXBeeInput( xd )
        dt.utcnow.return_value = 123
        xp.process( env )
        send.assert_called_once_with( 622, {'name': 'Garage Temperature', 'units': 'F', 'steps': ['step.ZigbeeAnalogNumberToVolts', 'step.TMP_36_Volts_to_Centigrade', 'step.Centigrade_to_Fahrenheit', 'step.Average', 'step.FormatValue', 'step.CurrentValue', 'step.oneInN', 'outputs.COSM'], 'at': 123, 'device': '0x13a200409029bf', 'port': 'adc-1'}, ['step.ZigbeeAnalogNumberToVolts', 'step.TMP_36_Volts_to_Centigrade', 'step.Centigrade_to_Fahrenheit', 'step.Average', 'step.FormatValue', 'step.CurrentValue', 'step.oneInN', 'outputs.COSM'] )

# ProcessCommandInput

    def test_ProcessCommandInputs_logger_name( self ):
        devices = {'device': {'port': {}}}
        psr = ProcessCommandInput( devices )
        self.assertEqual( psr.logger_name, Constants.LogKeys.INPUT_COMMANDS )

    @patch( 'housemonitor.inputs.processinput.Common.send' )
    def test_ProcessCommandInputs_process( self, send ):
        devices = {'device': {'port': {}}}
        env = DataEnvelope( Constants.EnvelopeTypes.STATUS, steps=['a', 'b', 'c'], value=555 )
        psr = ProcessCommandInput( devices )
        psr.process( env )
        send.assert_called_once_with( 555, env.args, ['a', 'b', 'c'] )

# ProcessStatusRequests

    def test_ProcessStatusRequests_logger_name( self ):
        devices = {'device': {'port': {}}}
        psr = ProcessStatusRequests( devices )
        self.assertEqual( psr.logger_name, Constants.LogKeys.INPUT_STATUS )

    @patch( 'housemonitor.inputs.processinput.Common.send' )
    def test_ProcessStatusRequests_process( self, send ):
        devices = {'device': {'port': {}}}
        data = {Constants.EnvelopeContents.STEPS: ['a', 'b', 'c'], Constants.EnvelopeContents.VALUE: 555}
        env = DataEnvelope( Constants.EnvelopeTypes.STATUS, **data )
        psr = ProcessStatusRequests( devices )
        psr.process( env )
        send.assert_called_once_with( 555, env.args, env[Constants.EnvelopeContents.STEPS] )

# ProcessInput

    @patch( 'housemonitor.inputs.processinput.xmlDeviceConfiguration.configure' )
    def testProcessInput_topic_name( self, config ):
        devices = {'device': {'port': {}}}
        pi = ProcessInput( devices )
        self.assertEqual( pi.topic_name, Constants.TopicNames.ProcessInputs )

    @patch( 'housemonitor.inputs.processinput.xmlDeviceConfiguration.configure' )
    def testProcessInput_configuration_file_name( self, config ):
        devices = {'device': {'port': {}}}
        pi = ProcessInput( devices )
        self.assertEqual( pi.configuration_file_name, 'housemonitor.inputs.processinput' )

    @patch( 'housemonitor.inputs.processinput.xmlDeviceConfiguration.configure' )
    def test_ProcessInput_logger_name( self, config ):
        devices = {'device': {'port': {}}}
        pi = ProcessInput( devices )
        self.assertEqual( pi.logger_name, Constants.LogKeys.inputs )

    @patch.object( ProcessXBeeInput, 'process' )
    @patch( 'housemonitor.inputs.processinput.xmlDeviceConfiguration.configure' )
    @patch.object( HMQueue, 'receive' )
    def test_ProcessInput_work_xbee_input( self, process, config, receive ):
        envelope = DataEnvelope( Constants.EnvelopeTypes.XBEE )
        que = HMQueue()
        pi = ProcessInput( que )
        que.receive.return_value = envelope
        pi.work()
        que.receive.assert_called_oncy_with()
        pi.commands[envelope.type].process.assert_called_once_with( envelope )

    @patch.object( ProcessStatusRequests, 'process' )
    @patch( 'housemonitor.inputs.processinput.xmlDeviceConfiguration.configure' )
    @patch.object( HMQueue, 'receive' )
    def test_ProcessInput_work_status_request( self, process, config, receive ):
        envelope = DataEnvelope( Constants.EnvelopeTypes.STATUS )
        que = HMQueue()
        pi = ProcessInput( que )
        que.receive.return_value = envelope
        pi.work()
        que.receive.assert_called_oncy_with()
        pi.commands[envelope.type].process.assert_called_once_with( envelope )

    def side_effect( self ):
        self.pi.forever = False

    @patch.object( HMQueue, 'receive' )
    @patch.object( ProcessInput, 'work' )
    @patch( 'housemonitor.inputs.processinput.xmlDeviceConfiguration.configure' )
    def test_input( self, receive, work, config ):
        que = HMQueue()
        self.pi = ProcessInput( que )
        work.side_effect = self.side_effect
        self.pi.input()
        self.pi.work.assert_called_once_with()
Exemplo n.º 7
0
 def test_input(self, receive, work, config):
     que = HMQueue()
     self.pi = ProcessInput(que)
     work.side_effect = self.side_effect
     self.pi.input()
     self.pi.work.assert_called_once_with()
Exemplo n.º 8
0
 def test_ProcessInput_logger_name(self, config):
     devices = {'device': {'port': {}}}
     pi = ProcessInput(devices)
     self.assertEqual(pi.logger_name, Constants.LogKeys.inputs)
Exemplo n.º 9
0
 def testProcessInput_configuration_file_name(self, config):
     devices = {'device': {'port': {}}}
     pi = ProcessInput(devices)
     self.assertEqual(pi.configuration_file_name,
                      'housemonitor.inputs.processinput')
Exemplo n.º 10
0
 def testProcessInput_topic_name(self, config):
     devices = {'device': {'port': {}}}
     pi = ProcessInput(devices)
     self.assertEqual(pi.topic_name, Constants.TopicNames.ProcessInputs)
Exemplo n.º 11
0
class Test(unittest.TestCase):
    logger = logging.getLogger('UnitTest')

    valid_devices_configuration = {
        '0x13a200408cccc3': {
            'adc-0': {
                'cosm_channel':
                '3',
                'description':
                'The temperature in the sunroom',
                'name':
                'Indoor Temperature',
                'steps': [
                    'step.ZigbeeAnalogNumberToVolts',
                    'step.TMP_36_Volts_to_Centigrade',
                    'step.Centigrade_to_Fahrenheit', 'step.Average',
                    'step.FormatValue', 'step.CurrentValue'
                ],
                'units':
                'F'
            },
            'adc-1': {
                'cosm_channel':
                '3',
                'description':
                'The temperature at 100 West Lisa Drive Austin TX',
                'name':
                'Outdoor Temperature',
                'steps': [
                    'step.ZigbeeAnalogNumberToVolts',
                    'step.TMP_36_Volts_to_Centigrade',
                    'step.Centigrade_to_Fahrenheit', 'step.Average',
                    'step.FormatValue', 'step.CurrentValue'
                ],
                'units':
                'F'
            },
            'name': 'Sunroom',
            'network_address': '0xf9f2'
        },
        '0x13a200409029bf': {
            'adc-1': {
                'cosm_channel':
                '2',
                'description':
                'The temperature above the garage door',
                'name':
                'Garage Temperature',
                'steps': [
                    'step.ZigbeeAnalogNumberToVolts',
                    'step.TMP_36_Volts_to_Centigrade',
                    'step.Centigrade_to_Fahrenheit', 'step.Average',
                    'step.FormatValue', 'step.CurrentValue', 'step.oneInN',
                    'outputs.COSM'
                ],
                'units':
                'F'
            },
            'dio-0': {
                'cosm_channel':
                '1',
                'description':
                'Monitors whether the garage door is open or closed.',
                'name':
                'Garage Door Monitor',
                'network_address':
                '0xf9f2',
                'steps': [
                    'step.garage_door_state', 'step.CurrentValue',
                    'step.onBooleanChange', 'outputs.COSM'
                ]
            },
            'name': 'Garage Door XBee Monitor',
            'network_address': '0xf9f2'
        }
    }

    def setUp(self):
        logging.config.fileConfig("unittest_logging.conf")

    def tearDown(self):
        pass

# ProcessXBeeInput

    def test_ProcessXBeeInput_logger_name(self):
        devices = {'device': {'port': {}}}
        pxi = ProcessXBeeInput(devices)
        self.assertEqual(pxi.logger_name, Constants.LogKeys.inputsZigBee)

    @patch('housemonitor.inputs.processinput.Common.send')
    @patch('housemonitor.inputs.processinput.xmlDeviceConfiguration.configure')
    def test_XBeeInput_process_invalid_device_error(self, config, send):
        data = {
            'source_addr_long': '\x00\x13\xa2\x00@\x90)\xbf',
            'source_addr': '\xf9\xf2',
            'id': 'rx_io_data_long_addr',
            'samples': [{
                'adc-1': 622
            }],
            'options': '\x01'
        }
        env = DataEnvelope(Constants.EnvelopeTypes.XBEE, **data)

        xd = xmlDeviceConfiguration()
        xd.devices = {
            '0x13a200408cccc3': {
                'adc-0': {
                    'cosm_channel':
                    '3',
                    'description':
                    'The temperature in the sunroom',
                    'name':
                    'Indoor Temperature',
                    'steps': [
                        'step.ZigbeeAnalogNumberToVolts',
                        'step.TMP_36_Volts_to_Centigrade',
                        'step.Centigrade_to_Fahrenheit', 'step.Average',
                        'step.FormatValue', 'step.CurrentValue'
                    ],
                    'units':
                    'F'
                },
                'adc-1': {
                    'cosm_channel':
                    '3',
                    'description':
                    'The temperature at 100 West Lisa Drive Austin TX',
                    'name':
                    'Outdoor Temperature',
                    'steps': [
                        'step.ZigbeeAnalogNumberToVolts',
                        'step.TMP_36_Volts_to_Centigrade',
                        'step.Centigrade_to_Fahrenheit', 'step.Average',
                        'step.FormatValue', 'step.CurrentValue'
                    ],
                    'units':
                    'F'
                },
                'name': 'Sunroom',
                'network_address': '0xf9f2'
            }
        }

        xp = ProcessXBeeInput(xd)
        xp.logger.exception = MagicMock()
        value = xp.process(env)
        xp.logger.exception.assert_called_with(
            "'Invalid device (0x13a200409029bf)'")
        self.assertEqual(send.call_count, 0)

    @patch('housemonitor.inputs.processinput.Common.send')
    @patch('housemonitor.inputs.processinput.xmlDeviceConfiguration.configure')
    def test_XBeeInput_process_invalid_port_error(self, config, send):

        data = {
            'source_addr_long': '\x00\x13\xa2\x00@\x90)\xbf',
            'source_addr': '\xf9\xf2',
            'id': 'rx_io_data_long_addr',
            'samples': [{
                'adc-3': 622
            }],
            'options': '\x01'
        }
        env = DataEnvelope(Constants.EnvelopeTypes.XBEE, **data)

        xd = xmlDeviceConfiguration()
        xd.devices = {
            '0x13a200409029bf': {
                'adc-0': {
                    'cosm_channel':
                    '3',
                    'description':
                    'The temperature in the sunroom',
                    'name':
                    'Indoor Temperature',
                    'steps': [
                        'step.ZigbeeAnalogNumberToVolts',
                        'step.TMP_36_Volts_to_Centigrade',
                        'step.Centigrade_to_Fahrenheit', 'step.Average',
                        'step.FormatValue', 'step.CurrentValue'
                    ],
                    'units':
                    'F'
                },
                'adc-1': {
                    'cosm_channel':
                    '3',
                    'description':
                    'The temperature at 100 West Lisa Drive Austin TX',
                    'name':
                    'Outdoor Temperature',
                    'steps': [
                        'step.ZigbeeAnalogNumberToVolts',
                        'step.TMP_36_Volts_to_Centigrade',
                        'step.Centigrade_to_Fahrenheit', 'step.Average',
                        'step.FormatValue', 'step.CurrentValue'
                    ],
                    'units':
                    'F'
                },
                'name': 'Sunroom',
                'network_address': '0xf9f2'
            }
        }

        xp = ProcessXBeeInput(xd)
        xp.logger.exception = MagicMock()
        value = xp.process(env)
        xp.logger.exception.assert_called_with("'Invalid port (adc-3)'")
        self.assertEqual(send.call_count, 0)

    @patch('housemonitor.inputs.processinput.Common.send')
    @patch('housemonitor.inputs.processinput.xmlDeviceConfiguration.configure')
    def test_XBeeInput_process_invalid_configuration_options_error(
            self, config, send):

        data = {
            'source_addr_long': '\x00\x13\xa2\x00@\x90)\xbf',
            'source_addr': '\xf9\xf2',
            'id': 'rx_io_data_long_addr',
            'samples': [{
                'adc-0': 622
            }],
            'options': '\x01'
        }
        env = DataEnvelope(Constants.EnvelopeTypes.XBEE, **data)

        xd = xmlDeviceConfiguration()
        xd.devices = {
            '0x13a200409029bf': {
                'adc-0': {
                    'cosm_channel':
                    '3',
                    'description':
                    'The temperature in the sunroom',
                    'name':
                    'Indoor Temperature',
                    'steps': [
                        'step.ZigbeeAnalogNumberToVolts',
                        'step.TMP_36_Volts_to_Centigrade',
                        'step.Centigrade_to_Fahrenheit', 'step.Average',
                        'step.FormatValue', 'step.CurrentValue'
                    ]
                },
                'adc-1': {
                    'cosm_channel':
                    '3',
                    'description':
                    'The temperature at 100 West Lisa Drive Austin TX',
                    'name':
                    'Outdoor Temperature',
                    'steps': [
                        'step.ZigbeeAnalogNumberToVolts',
                        'step.TMP_36_Volts_to_Centigrade',
                        'step.Centigrade_to_Fahrenheit', 'step.Average',
                        'step.FormatValue', 'step.CurrentValue'
                    ],
                    'units':
                    'F'
                },
                'name': 'Sunroom',
                'network_address': '0xf9f2'
            }
        }

        xp = ProcessXBeeInput(xd)
        xp.logger.exception = MagicMock()
        value = xp.process(env)
        xp.logger.exception.assert_called_with(
            "'Required configuration option not present (units) for device(0x13a200409029bf) port (adc-0)'"
        )
        self.assertEqual(send.call_count, 0)

    @patch('housemonitor.inputs.processinput.datetime')
    @patch('housemonitor.inputs.processinput.Common.send')
    @patch('housemonitor.inputs.processinput.xmlDeviceConfiguration.configure')
    def test_XBeeInput_process_with_valid_data(self, config, send, dt):
        test_time = datetime.datetime(2012, 1, 2, 3, 4, 5)
        data = {
            'source_addr_long': '\x00\x13\xa2\x00@\x90)\xbf',
            'source_addr': '\xf9\xf2',
            'id': 'rx_io_data_long_addr',
            'samples': [{
                'adc-1': 622
            }],
            'options': '\x01'
        }
        env = DataEnvelope(Constants.EnvelopeTypes.XBEE, **data)

        xd = xmlDeviceConfiguration()
        xd.devices = self.valid_devices_configuration
        xp = ProcessXBeeInput(xd)
        dt.utcnow.return_value = 123
        xp.process(env)
        send.assert_called_once_with(
            622, {
                'name':
                'Garage Temperature',
                'units':
                'F',
                'steps': [
                    'step.ZigbeeAnalogNumberToVolts',
                    'step.TMP_36_Volts_to_Centigrade',
                    'step.Centigrade_to_Fahrenheit', 'step.Average',
                    'step.FormatValue', 'step.CurrentValue', 'step.oneInN',
                    'outputs.COSM'
                ],
                'at':
                123,
                'device':
                '0x13a200409029bf',
                'port':
                'adc-1'
            }, [
                'step.ZigbeeAnalogNumberToVolts',
                'step.TMP_36_Volts_to_Centigrade',
                'step.Centigrade_to_Fahrenheit', 'step.Average',
                'step.FormatValue', 'step.CurrentValue', 'step.oneInN',
                'outputs.COSM'
            ])

# ProcessCommandInput

    def test_ProcessCommandInputs_logger_name(self):
        devices = {'device': {'port': {}}}
        psr = ProcessCommandInput(devices)
        self.assertEqual(psr.logger_name, Constants.LogKeys.INPUT_COMMANDS)

    @patch('housemonitor.inputs.processinput.Common.send')
    def test_ProcessCommandInputs_process(self, send):
        devices = {'device': {'port': {}}}
        env = DataEnvelope(Constants.EnvelopeTypes.STATUS,
                           steps=['a', 'b', 'c'],
                           value=555)
        psr = ProcessCommandInput(devices)
        psr.process(env)
        send.assert_called_once_with(555, env.args, ['a', 'b', 'c'])

# ProcessStatusRequests

    def test_ProcessStatusRequests_logger_name(self):
        devices = {'device': {'port': {}}}
        psr = ProcessStatusRequests(devices)
        self.assertEqual(psr.logger_name, Constants.LogKeys.INPUT_STATUS)

    @patch('housemonitor.inputs.processinput.Common.send')
    def test_ProcessStatusRequests_process(self, send):
        devices = {'device': {'port': {}}}
        data = {
            Constants.EnvelopeContents.STEPS: ['a', 'b', 'c'],
            Constants.EnvelopeContents.VALUE: 555
        }
        env = DataEnvelope(Constants.EnvelopeTypes.STATUS, **data)
        psr = ProcessStatusRequests(devices)
        psr.process(env)
        send.assert_called_once_with(555, env.args,
                                     env[Constants.EnvelopeContents.STEPS])


# ProcessInput

    @patch('housemonitor.inputs.processinput.xmlDeviceConfiguration.configure')
    def testProcessInput_topic_name(self, config):
        devices = {'device': {'port': {}}}
        pi = ProcessInput(devices)
        self.assertEqual(pi.topic_name, Constants.TopicNames.ProcessInputs)

    @patch('housemonitor.inputs.processinput.xmlDeviceConfiguration.configure')
    def testProcessInput_configuration_file_name(self, config):
        devices = {'device': {'port': {}}}
        pi = ProcessInput(devices)
        self.assertEqual(pi.configuration_file_name,
                         'housemonitor.inputs.processinput')

    @patch('housemonitor.inputs.processinput.xmlDeviceConfiguration.configure')
    def test_ProcessInput_logger_name(self, config):
        devices = {'device': {'port': {}}}
        pi = ProcessInput(devices)
        self.assertEqual(pi.logger_name, Constants.LogKeys.inputs)

    @patch.object(ProcessXBeeInput, 'process')
    @patch('housemonitor.inputs.processinput.xmlDeviceConfiguration.configure')
    @patch.object(HMQueue, 'receive')
    def test_ProcessInput_work_xbee_input(self, process, config, receive):
        envelope = DataEnvelope(Constants.EnvelopeTypes.XBEE)
        que = HMQueue()
        pi = ProcessInput(que)
        que.receive.return_value = envelope
        pi.work()
        que.receive.assert_called_oncy_with()
        pi.commands[envelope.type].process.assert_called_once_with(envelope)

    @patch.object(ProcessStatusRequests, 'process')
    @patch('housemonitor.inputs.processinput.xmlDeviceConfiguration.configure')
    @patch.object(HMQueue, 'receive')
    def test_ProcessInput_work_status_request(self, process, config, receive):
        envelope = DataEnvelope(Constants.EnvelopeTypes.STATUS)
        que = HMQueue()
        pi = ProcessInput(que)
        que.receive.return_value = envelope
        pi.work()
        que.receive.assert_called_oncy_with()
        pi.commands[envelope.type].process.assert_called_once_with(envelope)

    def side_effect(self):
        self.pi.forever = False

    @patch.object(HMQueue, 'receive')
    @patch.object(ProcessInput, 'work')
    @patch('housemonitor.inputs.processinput.xmlDeviceConfiguration.configure')
    def test_input(self, receive, work, config):
        que = HMQueue()
        self.pi = ProcessInput(que)
        work.side_effect = self.side_effect
        self.pi.input()
        self.pi.work.assert_called_once_with()
Exemplo n.º 12
0
class HouseMonitor():
    '''
    House Monitor is the main program responsible for starting the housemonitor
    system.  It performs the the following functions:

    1. Set up logging
    2. Print out start message
    3. Parse and set option passed in form the command line
    4. Sets up data that will be available to the rest of the system
    5. Loads all the modules that are in the directory steps
    6. Starts COSM for communicating with COSM.
    7. Starts XMLRPC.
    8. Starts
    '''
    TEST_MODE = False

    logger = None
    options = None
    args = None

    input = None
    input_queue = None
    test_input = None
    xbee_thread = None
    sched = None

    moduleloader = None
    cosm = None
    xmlrpc = None
    zigbee = None
    pubAid = None

    def __init__(self):

        logging.config.fileConfig("house_monitor_logging.conf")
        self.logger = logging.getLogger('HouseMonitor')

        self.print_start_message()
        self.parse_options()

    def print_start_message(self):
        '''
        Format and display the title.
        '''

        TITLE_FORMAT = '''


{:^30}

author:       {}
email:        {}
version:      {}
date built:   {}

'''
        title = self.TITLE_FORMAT.format(HOUSEMONITORTITLE, HOUSEMONITORAUTHOR,
                                         HOUSEMONITOREMAIL,
                                         HOUSEMONITORVERSION,
                                         HOUSEMONITORBUILDDATE)

        self.logger.info(title)

    def parse_options(self):
        global TEST_MODE
        Options = OptionParser()
        Options.add_option("-d",
                           action="store_false",
                           dest="display_data",
                           default=True)
        Options.add_option("-r",
                           action="store_true",
                           dest="display_response",
                           default=False,
                           help="display the data that is received")
        Options.add_option("-j",
                           action="store_true",
                           dest="display_json",
                           default=False,
                           help="display the json that is produced")
        Options.add_option("--http",
                           action="store_const",
                           default=False,
                           const=0,
                           dest="http2lib_debug_level",
                           help="Set the debug level for http2lib")
        Options.add_option("--test",
                           action="store_true",
                           default=False,
                           dest="in_test_mode",
                           help="Run in test mode.")
        (self.options, self.args) = Options.parse_args()

    def startInputs(self, global_data):
        ''' Start Home Monitor Input routines '''

        input_queue = global_data[Constants.GlobalData.INPUT_QUEUE]
        self.input = ProcessInput(input_queue)

        # Start thread for inputing data
        if (not self.options.in_test_mode):
            self.logger.debug('Starting xbee input')
            self.xbee_thread = XBeeInputThread(input_queue)
            self.xbee_thread.start()

        # The following will test various inputs
        if (self.options.in_test_mode):
            self.logger.debug('Starting test thread')
            self.test_input = TestInputThread(input_queue)
            self.test_input.start()

        self.logger.debug('Starting scheduler')
        self.sched = HMScheduler(input_queue)
        self.sched.start()

        if (sys.platform[:5] == 'linux' and not self.options.in_test_mode):
            self.logger.debug('Starting ComputerMonitor')
            self.computer_monitor = ComputerMonitor(input_queue)
            self.computer_monitor.start()

    def startOutputs(self, global_data):

        self.logger.debug('Start output communications to COSM')
        self.cosm = COSMControl()
        self.cosm.startCOSM(self.options)

        self.logger.debug('Start the XML RPC server')
        self.xmlrpc = XMLRPCControl(
            global_data[Constants.GlobalData.CURRENT_VALUES],
            global_data[Constants.GlobalData.INPUT_QUEUE],
            global_data[Constants.GlobalData.OPTIONS])
        self.xmlrpc.startXMLRPC(self.options)

        # Start thread for outputing data
        self.logger.debug('Start output communications with ZigBee')
        self.zigbee = ZigBeeControl()
        self.zigbee.startZigBee(self.options.in_test_mode)

    def run(self):

        self.logger.debug('Setting up global_data')
        global_data = {}
        global_data[Constants.GlobalData.CURRENT_VALUES] = CurrentValues()
        global_data[Constants.GlobalData.OPTIONS] = self.options
        global_data[Constants.GlobalData.ARGS] = self.args
        global_data[Constants.GlobalData.START_TIME] = datetime.utcnow()
        global_data[Constants.GlobalData.INPUT_QUEUE] = HMQueue("Input")

        self.module_loader = ModuleLoader()
        self.module_loader.load(global_data)

        self.startOutputs(global_data)

        self.startInputs(global_data)

        self.pubAid = PubSubAid()

        # Endless loop will never return
        self.input.input()

        self.logger.debug("Exiting")
Exemplo n.º 13
0
class HouseMonitor():
    '''
    House Monitor is the main program responsible for starting the housemonitor
    system.  It performs the the following functions:

    1. Set up logging
    2. Print out start message
    3. Parse and set option passed in form the command line
    4. Sets up data that will be available to the rest of the system
    5. Loads all the modules that are in the directory steps
    6. Starts COSM for communicating with COSM.
    7. Starts XMLRPC.
    8. Starts
    '''
    TEST_MODE = False

    logger = None
    options = None
    args = None

    input = None
    input_queue = None
    test_input = None
    xbee_thread = None
    sched = None

    moduleloader = None
    cosm = None
    xmlrpc = None
    zigbee = None
    pubAid = None


    def __init__( self ):

        logging.config.fileConfig( "house_monitor_logging.conf" )
        self.logger = logging.getLogger( 'HouseMonitor' )

        self.print_start_message()
        self.parse_options()

    def print_start_message( self ):
        '''
        Format and display the title.
        '''

        TITLE_FORMAT = '''


{:^30}

author:       {}
email:        {}
version:      {}
date built:   {}

'''
        title = self.TITLE_FORMAT.format( HOUSEMONITORTITLE,
                                          HOUSEMONITORAUTHOR,
                                          HOUSEMONITOREMAIL,
                                          HOUSEMONITORVERSION,
                                          HOUSEMONITORBUILDDATE )

        self.logger.info( title )

    def parse_options( self ):
        global TEST_MODE
        Options = OptionParser()
        Options.add_option( "-d",
                           action="store_false",
                           dest="display_data",
                           default=True )
        Options.add_option( "-r",
                           action="store_true",
                           dest="display_response",
                           default=False,
                           help="display the data that is received" )
        Options.add_option( "-j",
                           action="store_true",
                           dest="display_json",
                           default=False,
                           help="display the json that is produced" )
        Options.add_option( "--http",
                           action="store_const",
                           default=False,
                           const=0,
                           dest="http2lib_debug_level",
                           help="Set the debug level for http2lib" )
        Options.add_option( "--test",
                           action="store_true",
                           default=False,
                           dest="in_test_mode",
                           help="Run in test mode." )
        ( self.options, self.args ) = Options.parse_args()

    def startInputs( self, global_data ):
        ''' Start Home Monitor Input routines '''

        input_queue = global_data[Constants.GlobalData.INPUT_QUEUE]
        self.input = ProcessInput( input_queue )

        # Start thread for inputing data
        if ( not self.options.in_test_mode ):
            self.logger.debug( 'Starting xbee input' )
            self.xbee_thread = XBeeInputThread( input_queue )
            self.xbee_thread.start()

        # The following will test various inputs
        if ( self.options.in_test_mode ):
            self.logger.debug( 'Starting test thread' )
            self.test_input = TestInputThread( input_queue )
            self.test_input.start()

        self.logger.debug( 'Starting scheduler' )
        self.sched = HMScheduler( input_queue )
        self.sched.start()

        if ( sys.platform[:5] == 'linux' and
            not self.options.in_test_mode ):
            self.logger.debug( 'Starting ComputerMonitor' )
            self.computer_monitor = ComputerMonitor( input_queue )
            self.computer_monitor.start()

    def startOutputs( self, global_data ):

        self.logger.debug( 'Start output communications to COSM' )
        self.cosm = COSMControl()
        self.cosm.startCOSM( self.options )

        self.logger.debug( 'Start the XML RPC server' )
        self.xmlrpc = XMLRPCControl( 
                            global_data[Constants.GlobalData.CURRENT_VALUES],
                            global_data[Constants.GlobalData.INPUT_QUEUE],
                            global_data[Constants.GlobalData.OPTIONS] )
        self.xmlrpc.startXMLRPC( self.options )

        # Start thread for outputing data
        self.logger.debug( 'Start output communications with ZigBee' )
        self.zigbee = ZigBeeControl()
        self.zigbee.startZigBee( self.options.in_test_mode )

    def run( self ):

        self.logger.debug( 'Setting up global_data' )
        global_data = {}
        global_data[Constants.GlobalData.CURRENT_VALUES] = CurrentValues()
        global_data[Constants.GlobalData.OPTIONS] = self.options
        global_data[Constants.GlobalData.ARGS] = self.args
        global_data[Constants.GlobalData.START_TIME] = datetime.utcnow()
        global_data[Constants.GlobalData.INPUT_QUEUE] = HMQueue( "Input" )

        self.module_loader = ModuleLoader()
        self.module_loader.load( global_data )

        self.startOutputs( global_data )

        self.startInputs( global_data )

        self.pubAid = PubSubAid()

        # Endless loop will never return
        self.input.input()

        self.logger.debug( "Exiting" )