| @@ -6,12 +6,11 @@ Provides the full AD2 class and factory. | |||||
| import time | import time | ||||
| import threading | import threading | ||||
| import re | |||||
| from .event import event | from .event import event | ||||
| from . import devices | |||||
| from . import util | |||||
| from . import messages | |||||
| from . import zonetracking | |||||
| from .devices import USBDevice | |||||
| from .util import CommError, NoDeviceError | |||||
| from .messages import Message, ExpanderMessage, RFMessage, LRRMessage | |||||
| from .zonetracking import Zonetracker | |||||
| class Overseer(object): | class Overseer(object): | ||||
| """ | """ | ||||
| @@ -30,9 +29,9 @@ class Overseer(object): | |||||
| Returns all AD2USB devices located on the system. | Returns all AD2USB devices located on the system. | ||||
| :returns: list of devices found | :returns: list of devices found | ||||
| :raises: util.CommError | |||||
| :raises: CommError | |||||
| """ | """ | ||||
| cls.__devices = devices.USBDevice.find_all() | |||||
| cls.__devices = USBDevice.find_all() | |||||
| return cls.__devices | return cls.__devices | ||||
| @@ -54,18 +53,18 @@ class Overseer(object): | |||||
| :type device: tuple | :type device: tuple | ||||
| :returns: AD2USB object utilizing the specified device. | :returns: AD2USB object utilizing the specified device. | ||||
| :raises: util.NoDeviceError | |||||
| :raises: NoDeviceError | |||||
| """ | """ | ||||
| cls.find_all() | cls.find_all() | ||||
| if len(cls.__devices) == 0: | if len(cls.__devices) == 0: | ||||
| raise util.NoDeviceError('No AD2USB devices present.') | |||||
| raise NoDeviceError('No AD2USB devices present.') | |||||
| if device is None: | if device is None: | ||||
| device = cls.__devices[0] | device = cls.__devices[0] | ||||
| vendor, product, sernum, ifcount, description = device | vendor, product, sernum, ifcount, description = device | ||||
| device = devices.USBDevice((sernum, ifcount - 1)) | |||||
| device = USBDevice((sernum, ifcount - 1)) | |||||
| return AD2(device) | return AD2(device) | ||||
| @@ -163,7 +162,7 @@ class Overseer(object): | |||||
| for d in removed_devices: | for d in removed_devices: | ||||
| self._overseer.on_detached(d) | self._overseer.on_detached(d) | ||||
| except util.CommError, err: | |||||
| except CommError, err: | |||||
| pass | pass | ||||
| time.sleep(0.25) | time.sleep(0.25) | ||||
| @@ -220,10 +219,10 @@ class AD2(object): | |||||
| Constructor | Constructor | ||||
| :param device: The low-level device used for this AD2 interface. | :param device: The low-level device used for this AD2 interface. | ||||
| :type device: devices.Device | |||||
| :type device: Device | |||||
| """ | """ | ||||
| self._device = device | self._device = device | ||||
| self._zonetracker = zonetracking.Zonetracker() | |||||
| self._zonetracker = Zonetracker() | |||||
| self._power_status = None | self._power_status = None | ||||
| self._alarm_status = None | self._alarm_status = None | ||||
| @@ -271,7 +270,9 @@ class AD2(object): | |||||
| """ | """ | ||||
| Closes the device. | Closes the device. | ||||
| """ | """ | ||||
| self._device.close() | |||||
| if self._device: | |||||
| self._device.close() | |||||
| del self._device | del self._device | ||||
| self._device = None | self._device = None | ||||
| @@ -283,7 +284,7 @@ class AD2(object): | |||||
| """ | """ | ||||
| Retrieves the configuration from the device. | Retrieves the configuration from the device. | ||||
| """ | """ | ||||
| self._device.write("C\r") | |||||
| self.send("C\r") | |||||
| def save_config(self): | def save_config(self): | ||||
| """ | """ | ||||
| @@ -312,13 +313,13 @@ class AD2(object): | |||||
| config_string = '&'.join(['='.join(t) for t in config_entries]) | config_string = '&'.join(['='.join(t) for t in config_entries]) | ||||
| self._device.write("C{0}\r".format(config_string)) | |||||
| self.send("C{0}\r".format(config_string)) | |||||
| def reboot(self): | def reboot(self): | ||||
| """ | """ | ||||
| Reboots the device. | Reboots the device. | ||||
| """ | """ | ||||
| self._device.write('=') | |||||
| self.send('=') | |||||
| def fault_zone(self, zone, simulate_wire_problem=False): | def fault_zone(self, zone, simulate_wire_problem=False): | ||||
| """ | """ | ||||
| @@ -339,7 +340,7 @@ class AD2(object): | |||||
| status = 2 if simulate_wire_problem else 1 | status = 2 if simulate_wire_problem else 1 | ||||
| self._device.write("L{0:02}{1}\r".format(zone, status)) | |||||
| self.send("L{0:02}{1}\r".format(zone, status)) | |||||
| def clear_zone(self, zone): | def clear_zone(self, zone): | ||||
| """ | """ | ||||
| @@ -348,7 +349,7 @@ class AD2(object): | |||||
| :param zone: The zone to clear. | :param zone: The zone to clear. | ||||
| :type zone: int | :type zone: int | ||||
| """ | """ | ||||
| self._device.write("L{0:02}0\r".format(zone)) | |||||
| self.send("L{0:02}0\r".format(zone)) | |||||
| def _wire_events(self): | def _wire_events(self): | ||||
| """ | """ | ||||
| @@ -371,19 +372,19 @@ class AD2(object): | |||||
| :returns: An object representing the message. | :returns: An object representing the message. | ||||
| """ | """ | ||||
| if data is None: | if data is None: | ||||
| return None | |||||
| raise InvalidMessageError() | |||||
| msg = None | msg = None | ||||
| header = data[0:4] | header = data[0:4] | ||||
| if header[0] != '!' or header == '!KPE': | if header[0] != '!' or header == '!KPE': | ||||
| msg = messages.Message(data) | |||||
| msg = Message(data) | |||||
| if self.address_mask & msg.mask > 0: | if self.address_mask & msg.mask > 0: | ||||
| self._update_internal_states(msg) | self._update_internal_states(msg) | ||||
| elif header == '!EXP' or header == '!REL': | elif header == '!EXP' or header == '!REL': | ||||
| msg = messages.ExpanderMessage(data) | |||||
| msg = ExpanderMessage(data) | |||||
| self._update_internal_states(msg) | self._update_internal_states(msg) | ||||
| @@ -402,7 +403,7 @@ class AD2(object): | |||||
| return msg | return msg | ||||
| def _handle_rfx(self, data): | def _handle_rfx(self, data): | ||||
| msg = messages.RFMessage(data) | |||||
| msg = RFMessage(data) | |||||
| self.on_rfx_message(msg) | self.on_rfx_message(msg) | ||||
| @@ -417,7 +418,7 @@ class AD2(object): | |||||
| :returns: An object representing the LRR message. | :returns: An object representing the LRR message. | ||||
| """ | """ | ||||
| msg = messages.LRRMessage(data) | |||||
| msg = LRRMessage(data) | |||||
| if msg.event_type == 'ALARM_PANIC': | if msg.event_type == 'ALARM_PANIC': | ||||
| self._panic_status = True | self._panic_status = True | ||||
| @@ -469,7 +470,7 @@ class AD2(object): | |||||
| :param message: Message to update internal states with. | :param message: Message to update internal states with. | ||||
| :type message: Message, ExpanderMessage, LRRMessage, or RFMessage | :type message: Message, ExpanderMessage, LRRMessage, or RFMessage | ||||
| """ | """ | ||||
| if isinstance(message, messages.Message): | |||||
| if isinstance(message, Message): | |||||
| if message.ac_power != self._power_status: | if message.ac_power != self._power_status: | ||||
| self._power_status, old_status = message.ac_power, self._power_status | self._power_status, old_status = message.ac_power, self._power_status | ||||
| @@ -511,8 +512,8 @@ class AD2(object): | |||||
| self._fire_status = (message.fire_alarm, time.time()) | self._fire_status = (message.fire_alarm, time.time()) | ||||
| self.on_fire(self._fire_status) | self.on_fire(self._fire_status) | ||||
| elif isinstance(message, messages.ExpanderMessage): | |||||
| if message.type == messages.ExpanderMessage.RELAY: | |||||
| elif isinstance(message, ExpanderMessage): | |||||
| if message.type == ExpanderMessage.RELAY: | |||||
| self._relay_status[(message.address, message.channel)] = message.value | self._relay_status[(message.address, message.channel)] = message.value | ||||
| self.on_relay_changed(message) | self.on_relay_changed(message) | ||||
| @@ -529,9 +530,9 @@ class AD2(object): | |||||
| # Retrieve a list of faults. | # Retrieve a list of faults. | ||||
| # NOTE: This only happens on first boot or after exiting programming mode. | # NOTE: This only happens on first boot or after exiting programming mode. | ||||
| if isinstance(message, messages.Message): | |||||
| if isinstance(message, Message): | |||||
| if not message.ready and "Hit * for faults" in message.text: | if not message.ready and "Hit * for faults" in message.text: | ||||
| self._device.write('*') | |||||
| self.send('*') | |||||
| return | return | ||||
| self._zonetracker.update(message) | self._zonetracker.update(message) | ||||