class Logger: def __init__(self, address, port): # connect to the cube self.cube = MaxCube(MaxCubeConnection(address, port)) def log(self, today): self.cube.update() now = time.strftime("%Y-%m-%d %H:%M") apartments = {} print(len(self.cube.devices), "devices found") for device in self.cube.devices: id = device.name.split("_")[0] if id not in apartments: apartments[id] = [] apartments[id].append(device) today_file = today + "-log.csv" if not Path(today_file).is_file(): # create a new file if it doesn't exist with open(today_file, "w") as file: file.write("time,apartment,thermostat,valve,temp\n") file.close() with open(today_file, "a") as file: row = ",".join([ now, id, device.name, str(device.valve_position), str(device.actual_temperature) ]) + "\n" file.write(row) file.close()
def init(self, ClassMock, responses): self.commander = ClassMock.return_value self.commander.update.return_value = responses self.cube = MaxCube("host", 1234, now=lambda: datetime(2012, 10, 22, 5, 30)) self.commander.update.assert_called_once() self.commander.update.reset_mock() self.commander.send_radio_msg.return_value = True
def refresh_topology(self): time.sleep(0.01) self.logger.debug('Starting topology refresh') try: self.connect() cube = MaxCube(self.__max_cube_connection) #TODO report cube values to the broker # self.__messageQ.put(self.prepare_output('cube', 'free_mem_slots', cube.free_mem_slots)) # self.__messageQ.put(self.prepare_output('cube', 'duty_cycle', cube.duty_cycle)) for device in cube.devices: device_id = self.update_device(device) if device.type in (MAX_THERMOSTAT, MAX_THERMOSTAT_PLUS, MAX_WALL_THERMOSTAT) \ and self.enable_sanity_check \ and (device_id in self.desired_temperatures) \ and (self.desired_temperatures[device_id] != device.target_temperature): try: self.logger.info( "Correcting temperature for device :%s (%s/%s) from:%s to:%s" % (device_id, device.room_name, device.name, device.target_temperature, self.desired_temperatures[device_id])) cube.set_target_temperature( device, self.desired_temperatures[device_id]) self.logger.info("Command result:%s" % cube.command_result) if cube.command_success: self.__messageQ.put( self.prepare_output( device_id, 'target_temperature', self.topology[device_id] ['target_temperature'])) self.__messageQ.put( self.prepare_output('cube', 'free_mem_slots', cube.free_mem_slots)) self.__messageQ.put( self.prepare_output('' 'cube', 'duty_cycle', cube.duty_cycle)) self.cube_duty_cycle = cube.duty_cycle self.cube_duty_cycle_reset = time.time() except Exception as e: self.logger.error("Set error:%s" % (format(e))) except Exception as e: self.logger.error(format(e)) self.logger.debug('Finished topology refresh') if self.update_timer_elapsed(): self.mqtt_last_refresh = time.time() self.dump_topology() return (True)
def onHeartbeat(self): #Cancel the rest of this function if this heartbeat needs to be skipped if self.beats < self.skipbeats: Domoticz.Debug("Skipping heartbeat: " + str(self.beats)) self.beats += 1 return self.beats=1 self.HeatDemand = 0 # Read data from Cube Domoticz.Debug("Reading e-Q3 MAX! devices from Cube...") try: cube = MaxCube(MaxCubeConnection(Parameters["Address"], int(Parameters["Port"]))) except: Domoticz.Error("Error connecting to Cube. Other running MAX! programs may block the communication!") return # Update devices in Domoticz for EQ3device in cube.devices: Domoticz.Debug("Checking device '" + EQ3device.name + "' in room " + str(EQ3device.room_id)) if cube.is_thermostat(EQ3device): # Check if valve requires heat if EQ3device.valve_position > int(Parameters["Mode4"]): self.HeatDemand += 1 # Update Domoticz devices for radiator valves self.UpdateDevice(EQ3device, "Valve") if not self.RoomHasThermostat[EQ3device.room_id]: self.UpdateDevice(EQ3device, "Thermostat") self.UpdateDevice(EQ3device, "Temperature") self.UpdateDevice(EQ3device, "Mode") elif cube.is_wallthermostat(EQ3device): # Update Domoticz devices for wall thermostats self.UpdateDevice(EQ3device, "Thermostat") self.UpdateDevice(EQ3device, "Temperature") self.UpdateDevice(EQ3device, "Mode") elif cube.is_windowshutter(EQ3device): # Look up & update Domoticz device for contact switches self.UpdateDevice(EQ3device, "Contact") # Update heat demand switch if necessary Domoticz.Debug(str(self.HeatDemand) + " valves require heat") if self.HeatDemand > 0 and Parameters["Mode3"] == "True" and 255 in Devices and Devices[255].sValue == "Off": Devices[255].Update(nValue=1, sValue="On") Domoticz.Log("Heat demand switch turned on") elif self.HeatDemand == 0 and Parameters["Mode3"] == "True" and 255 in Devices and Devices[255].sValue == "On": Devices[255].Update(nValue=0, sValue="Off") Domoticz.Log("Heat demand switch turned off")
def setup(hass, config): """Establish connection to MAX! Cube.""" from maxcube.connection import MaxCubeConnection from maxcube.cube import MaxCube if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} connection_failed = 0 gateways = config[DOMAIN][CONF_GATEWAYS] for gateway in gateways: host = gateway[CONF_HOST] port = gateway[CONF_PORT] try: cube = MaxCube(MaxCubeConnection(host, port)) hass.data[DATA_KEY][host] = MaxCubeHandle(cube) except timeout as ex: _LOGGER.error("Unable to connect to Max!Cube gateway: %s", str(ex)) hass.components.persistent_notification.create( 'Error: {}<br />' 'You will need to restart Home Assistant after fixing.' ''.format(ex), title=NOTIFICATION_TITLE, notification_id=NOTIFICATION_ID) connection_failed += 1 if connection_failed >= len(gateways): return False load_platform(hass, 'climate', DOMAIN) load_platform(hass, 'binary_sensor', DOMAIN) return True
def setup(hass: HomeAssistant, config: ConfigType) -> bool: """Establish connection to MAX! Cube.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} connection_failed = 0 gateways = config[DOMAIN][CONF_GATEWAYS] for gateway in gateways: host = gateway[CONF_HOST] port = gateway[CONF_PORT] scan_interval = gateway[CONF_SCAN_INTERVAL].total_seconds() try: cube = MaxCube(host, port, now=now) hass.data[DATA_KEY][host] = MaxCubeHandle(cube, scan_interval) except timeout as ex: _LOGGER.error("Unable to connect to Max!Cube gateway: %s", str(ex)) persistent_notification.create( hass, f"Error: {ex}<br />You will need to restart Home Assistant after fixing.", title=NOTIFICATION_TITLE, notification_id=NOTIFICATION_ID, ) connection_failed += 1 if connection_failed >= len(gateways): return False load_platform(hass, Platform.CLIMATE, DOMAIN, {}, config) load_platform(hass, Platform.BINARY_SENSOR, DOMAIN, {}, config) return True
def run(self): self.refresh_topology() self.topology_last_refresh = time.time() while True: time.sleep(0.01) # resetting internal duty cycle metric if time.time() > (self.cube_duty_cycle_reset + self.cube_duty_cycle_reset_interval): self.cube_duty_cycle = 0 self.cube_duty_cycle_reset = time.time() self.__messageQ.put(self.prepare_output( 'cube', 'duty_cycle', self.cube_duty_cycle)) # processing incoming data if not self.__commandQ.empty(): try: self.connect() cube = MaxCube(self.__max_cube_connection) while not self.__commandQ.empty(): task = self.__commandQ.get() if task['method'] == 'command': if task['param'] == 'target_temperature': self.set_temperature(cube,task['deviceId'],task['payload']) elif task['param'] == 'mode': self.set_mode(cube,task['deviceId'],task['payload']) self.logger.debug("Executing command:%s" % (task)) except Exception as e: self.logger.error(format(e)) # refreshing topology if self.update_timer_elapsed(): self.refresh_topology() self.topology_last_refresh = time.time() self.close()
def setup(hass, config): """Establish connection to MAX! Cube.""" from maxcube.connection import MaxCubeConnection from maxcube.cube import MaxCube # Read Config host = config.get(DOMAIN).get(CONF_HOST) port = config.get(DOMAIN).get(CONF_PORT) # Assign Cube Handle to global variable try: cube = MaxCube(MaxCubeConnection(host, port)) except timeout: _LOGGER.error("Connection to Max!Cube could not be established") cube = None return False hass.data[MAXCUBE_HANDLE] = MaxCubeHandle(cube) # Load Climate (for Thermostats) load_platform(hass, 'climate', DOMAIN) # Load BinarySensor (for Window Shutter) load_platform(hass, 'binary_sensor', DOMAIN) # Initialization successfull return True
def setup(hass, config): """Establish connection to MAX! Cube.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} connection_failed = 0 gateways = config[DOMAIN][CONF_GATEWAYS] for gateway in gateways: host = gateway[CONF_HOST] port = gateway[CONF_PORT] scan_interval = gateway[CONF_SCAN_INTERVAL].total_seconds() try: cube = MaxCube(MaxCubeConnection(host, port)) hass.data[DATA_KEY][host] = MaxCubeHandle(cube, scan_interval) except timeout as ex: _LOGGER.error("Unable to connect to Max!Cube gateway: %s", str(ex)) hass.components.persistent_notification.create( "Error: {}<br />" "You will need to restart Home Assistant after fixing." "".format(ex), title=NOTIFICATION_TITLE, notification_id=NOTIFICATION_ID, ) connection_failed += 1 if connection_failed >= len(gateways): return False load_platform(hass, "climate", DOMAIN, {}, config) load_platform(hass, "binary_sensor", DOMAIN, {}, config) return True
def __init__(self, address, port): # connect to the cube self.cube = MaxCube(MaxCubeConnection(address, port)) # setup the output mode on all the pins wiringpi.wiringPiSetup() wiringpi.pinMode(PIN1, 1) wiringpi.pinMode(PIN2, 1) wiringpi.pinMode(PIN3, 1) # pin_status dict contains the current status of the output pins # status 0 means that the pump is operating normally (turned on) # status 1 means that the pump is turned off (1 on the GPIO pin opens the relay) self.pin_status = {PIN1: 0, PIN2: 0, PIN3: 0} # map apartment IDs to the output pins self.pin_mapping = {"10": PIN1, "11": PIN2}
def onStart(self): # Set heartbeat self.skipbeats=int(Parameters["Mode5"])/30 self.beats=self.skipbeats Domoticz.Heartbeat(30) # Set debugging if Parameters["Mode6"]=="True": Domoticz.Debugging(2) Domoticz.Debug("Debugging mode activated") # Read Cube for intialization of devices Domoticz.Debug("Reading e-Q3 MAX! devices from Cube...") try: cube = MaxCube(MaxCubeConnection(Parameters["Address"], int(Parameters["Port"]))) except: Domoticz.Error("Error connecting to Cube. Other running MAX! programs may block the communication!") return # Check which rooms have a wall mounterd thermostat max_room = 0 for room in cube.rooms: if room.id > max_room: max_room = room.id Domoticz.Debug("Number of rooms found: " + str((len(cube.rooms))) + " (highest number: " + str(max_room) + ")") self.RoomHasThermostat=[False] * (max_room+1) for EQ3device in cube.devices: if cube.is_wallthermostat(EQ3device): self.RoomHasThermostat[EQ3device.room_id] = True Domoticz.Debug("Room " + str(EQ3device.room_id) + " (" + cube.room_by_id(EQ3device.room_id).name + ") has a thermostat") # Create or delete devices if necessary for EQ3device in cube.devices: if cube.is_thermostat(EQ3device): self.CheckDevice(EQ3device.name, EQ3device.rf_address, "Valve") if not self.RoomHasThermostat[EQ3device.room_id]: self.CheckDevice(EQ3device.name, EQ3device.rf_address, "Thermostat") self.CheckDevice(EQ3device.name, EQ3device.rf_address, "Temperature") self.CheckDevice(EQ3device.name, EQ3device.rf_address, "Mode") elif cube.is_wallthermostat(EQ3device): self.CheckDevice(EQ3device.name, EQ3device.rf_address, "Thermostat") self.CheckDevice(EQ3device.name, EQ3device.rf_address, "Temperature") self.CheckDevice(EQ3device.name, EQ3device.rf_address, "Mode") elif cube.is_windowshutter(EQ3device): self.CheckDevice(EQ3device.name, EQ3device.rf_address, "Contact") # Create or delete heat demand switch if necessary if Parameters["Mode3"] == "True" and 255 not in Devices: Domoticz.Device(Name="Heat demand", Unit=255, TypeName="Switch", Image=9, Used=1).Create() if 255 not in Devices: Domoticz.Error("Heat demand switch could not be created. Is 'Accept new Hardware Devices' enabled under Settings?") else: Domoticz.Log("Created device '" + Parameters["Name"] + " - Heat demand'") Devices[255].Update(nValue=0, sValue="Off") elif Parameters["Mode3"] == "False" and 255 in Devices: Devices[255].Delete() Domoticz.Log("Deleted heat demand switch")
def discover(self): try: self.cube = MaxCube(MaxCubeConnection(self.address, self.port)) except socket.timeout: logging.error('Could not connect to MAX! cube when setting up the bridge. ' 'Make sure nothing else is connected to the MAX! cube at start up and ' 'try again.') for device in self.cube.devices: if device.type != MAX_THERMOSTAT: logging.info('Discovered non-thermostat') continue self.add_accessory(Thermostat(self.cube, device, self.driver))
def onCommand(self, Unit, Command, Level, Hue): # Update commands for thermostats if Devices[Unit].Type == 242 and Devices[Unit].sValue != str(Level): Domoticz.Log("Setpoint changed for " + Devices[Unit].Name + ". New setpoint: " + str(Level)) try: cube = MaxCube(MaxCubeConnection(Parameters["Address"], int(Parameters["Port"]))) except: Domoticz.Error("Error connecting to Cube. Other running MAX! programs may block the communication!") return for EQ3device in cube.devices: if Devices[Unit].DeviceID == EQ3device.rf_address: cube.set_target_temperature(EQ3device, Level) Devices[Unit].Update(nValue=0, sValue=str(Level)) Devices[Unit].Refresh() # Update commands for mode switches if Devices[Unit].Type == 244 and Devices[Unit].SubType == 62 and Devices[Unit].sValue != str(Level): if Level == 00: mode = 0 mode_text = "Auto" elif Level == 10: mode = 1 mode_text = "Manual" elif Level == 20: mode = 2 mode_text = "Vacation" elif Level == 30: mode = 3 mode_text = "Boost" Domoticz.Log("Mode changed for " + Devices[Unit].Name + ". New mode: " + mode_text) try: cube = MaxCube(MaxCubeConnection(Parameters["Address"], int(Parameters["Port"]))) except: Domoticz.Error("Error connecting to Cube. Other running MAX! programs may block the communication!") return for EQ3device in cube.devices: if Devices[Unit].DeviceID == EQ3device.rf_address: cube.set_mode(EQ3device, mode) Devices[Unit].Update(nValue=0, sValue=str(Level)) Devices[Unit].Refresh()
def setup(hass, config): """Establish connection to MAX! Cube.""" from maxcube.connection import MaxCubeConnection from maxcube.cube import MaxCube host = config.get(DOMAIN).get(CONF_HOST) port = config.get(DOMAIN).get(CONF_PORT) try: cube = MaxCube(MaxCubeConnection(host, port)) except timeout: _LOGGER.error("Connection to Max!Cube could not be established") cube = None return False hass.data[MAXCUBE_HANDLE] = MaxCubeHandle(cube) load_platform(hass, 'climate', DOMAIN) load_platform(hass, 'binary_sensor', DOMAIN) return True
def check_maxdevices(app): if not serverIP: return # only check every 15 minutes global minuteCounter minuteCounter = minuteCounter + 1 if minuteCounter > 15: minuteCounter = 0 if minuteCounter != 0: return try: cube = MaxCube(MaxCubeConnection(serverIP, 62910)) except socket.timeout: print "MAX: Timeout..." return with app.app_context(): for device in cube.devices: if device.linkStatusError != 0: statusOk = False else: statusOk = True record = Hosts.query.filter_by(fqdn=device.name).first() if record: # update if MAX! device already exists record.status = statusOk record.last_checked = datetime.utcnow() else: # otherwise create a new entry host = Hosts(fqdn=device.name, friendly_name=None, status=statusOk, last_checked=datetime.utcnow(), type='MAX', idle_duration=60) db.session.add(host) db.session.commit()
def Connect(self): if not cBaseInterFaceSettings.Connect(self): return False if self.aInterFaceIniSettings.uHost == '': return False try: if self.oDevice is None: # self.oDevice = Cube(address=self.aInterFaceIniSettings.uHost, port=ToInt(self.aInterFaceIniSettings.uPort)) self.oDevice = MaxCube( MaxCubeConnection( host=self.aInterFaceIniSettings.uHost, port=ToInt(self.aInterFaceIniSettings.uPort))) # self.oDevice.connect() self.oInterFace.oInterFaceConfig.WriteDefinitionConfigPar( uSectionName=self.uSection, uVarName=u'OldDiscoveredIP', uVarValue=self.aInterFaceIniSettings.uHost) self.bIsConnected = True return self.bIsConnected except Exception as e: if hasattr(e, "errno"): if e.errno == 10051: self.bOnError = True self.ShowWarning(u'Cannot connect (No Network):' + self.aInterFaceIniSettings.uHost + ':' + self.aInterFaceIniSettings.uPort) return False self.ShowError( u'Cannot connect:' + self.aInterFaceIniSettings.uHost + ':' + self.aInterFaceIniSettings.uPort, e) self.bOnError = True return False
from maxcube.cube import MaxCube from maxcube.connection import MaxCubeConnection cube = MaxCube(MaxCubeConnection('192.168.0.20', 62910)) for device in cube.devices: print(device.name) print(device.actual_temperature) print(device.target_temperature) cube.set_target_temperature(device, 18) class MaxcubeMQTT:
def __init__(self): self.cube = MaxCube(MaxCubeConnection('192.168.1.186', 62910)) print "rooms:" for room in self.cube.get_rooms(): print "%s (%d)" % (room.name, room.id)
class CubeCtrl(object): ''' Wat gaan we doen: - haal kamers (naam, id) op - haal thermostaat per kamer op (naam, actual_temperature, target_temperature, valve_position) - - target temp ''' cube = None def __init__(self): self.cube = MaxCube(MaxCubeConnection('192.168.1.186', 62910)) print "rooms:" for room in self.cube.get_rooms(): print "%s (%d)" % (room.name, room.id) def get_info(self): room = self.cube.room_by_id(1) print("Room(1): " + room.name) for device in self.cube.devices_by_room(room): self.get_device_info(device) def set_temperature(self, room_id=1, temp=10.5): room = self.cube.room_by_id(1) for device in self.cube.devices_by_room(room): print(device) if self.cube.is_wallthermostat(device) or self.cube.is_thermostat(device): print("Setting temp to %s" % str(temp)) self.cube.set_target_temperature(device, temp) else: print("No Thermostat") def set_device_mode(self, device): print(device) if self.cube.is_wallthermostat(device): print("Setting mode") self.cube.set_mode(device, MAX_DEVICE_MODE_MANUAL) else: print("No Wall Thermostat") def get_device_info(self, device): print("Device: " + device.name) if device.type == MAX_THERMOSTAT: type = "MAX_THERMOSTAT" elif device.type == MAX_THERMOSTAT_PLUS: type = "MAX_THERMOSTAT_PLUS" elif device.type == MAX_WINDOW_SHUTTER: type = "MAX_WINDOW_SHUTTER" elif device.type == MAX_WALL_THERMOSTAT: type = "MAX_WALL_THERMOSTAT" print("Type: " + type) print("RF: " + device.rf_address) print("Room ID:" + str(device.room_id)) print("Room: " + self.cube.room_by_id(device.room_id).name) print("Name: " + device.name) print("Serial: " + device.serial) if device.type == MAX_THERMOSTAT: print("MaxSetP:" + str(device.max_temperature)) print("MinSetP:" + str(device.min_temperature)) if device.mode == MAX_DEVICE_MODE_AUTOMATIC: mode = "AUTO" elif device.mode == MAX_DEVICE_MODE_MANUAL: mode = "MANUAL" print("Mode: " + mode) print("Valve: " + str(device.valve_position)) print("Actual: " + str(device.actual_temperature)) print("Target: " + str(device.target_temperature)) if device.type == MAX_WALL_THERMOSTAT: print("MaxSetP:" + str(device.max_temperature)) print("MinSetP:" + str(device.min_temperature)) if device.mode == MAX_DEVICE_MODE_AUTOMATIC: mode = "AUTO" elif device.mode == MAX_DEVICE_MODE_MANUAL: mode = "MANUAL" print("Mode: " + mode) print("Actual: " + str(device.actual_temperature)) print("Target: " + str(device.target_temperature)) if device.type == MAX_WINDOW_SHUTTER: print("IsOpen: " + str(device.is_open)) print("")
import argparse import sys from maxcube.connection import MaxCubeConnection from maxcube.cube import MaxCube if __name__ == '__main__': parser = argparse.ArgumentParser( description='Set or dump thermostat programmes') parser.add_argument('--host', required=True) parser.add_argument('--port', required=True, type=int) parser.add_argument('cmd', choices=['load', 'dump']) args = parser.parse_args() cube = MaxCube(MaxCubeConnection(args.host, args.port)) if args.cmd == 'load': cube.set_programmes_from_config(sys.stdin) elif args.cmd == 'dump': print(cube.devices_as_json())
def setUp(self): self.cube = MaxCube(MaxCubeConnectionMock(INIT_RESPONSE_2))
class TestMaxCubeExtended(unittest.TestCase): """ Test the Max! Cube. """ def setUp(self): self.cube = MaxCube(MaxCubeConnectionMock(INIT_RESPONSE_2)) def test_init(self): self.assertEqual('015d2a', self.cube.rf_address) self.assertEqual('Cube', self.cube.name) self.assertEqual('01.13', self.cube.firmware_version) self.assertEqual(3, len(self.cube.devices)) def test_parse_response(self): self.cube.parse_response(INIT_RESPONSE_2) self.assertEqual('015d2a', self.cube.rf_address) self.assertEqual('Cube', self.cube.name) self.assertEqual('01.13', self.cube.firmware_version) self.assertEqual(3, len(self.cube.devices)) def test_parse_c_message_thermostat(self): device = self.cube.devices[0] self.assertEqual(21.5, device.comfort_temperature) self.assertEqual(16.5, device.eco_temperature) self.assertEqual(4.5, device.min_temperature) self.assertEqual(30.5, device.max_temperature) device = self.cube.devices[1] self.assertEqual(21.5, device.comfort_temperature) self.assertEqual(16.5, device.eco_temperature) self.assertEqual(4.5, device.min_temperature) self.assertEqual(30.5, device.max_temperature) device = self.cube.devices[2] self.assertEqual(1, device.initialized) def test_parse_h_message(self): self.cube.parse_h_message( 'H:KEQ0566338,0b6444,0113,00000000,335b04d2,33,32,0f0c1d,101c,03,0000' ) self.assertEqual('0b6444', self.cube.rf_address) self.assertEqual('01.13', self.cube.firmware_version) def test_parse_m_message(self): self.cube.parse_m_message( 'M:00,01,VgIEAQdLaXRjaGVuBrxTAgZMaXZpbmcGvFoDCFNsZWVwaW5nCKuCBARXb3JrBrxcBAEGvF' 'NLRVEwMzM2MTA4B0tpdGNoZW4BAQa8WktFUTAzMzYxMDAGTGl2aW5nAgEIq4JLRVEwMzM1NjYyCFNs' 'ZWVwaW5nAwEGvFxLRVEwMzM2MTA0BFdvcmsEAQ==') self.assertEqual('0E2EBA', self.cube.devices[0].rf_address) self.assertEqual('Thermostat', self.cube.devices[0].name) self.assertEqual(MAX_THERMOSTAT, self.cube.devices[0].type) self.assertEqual('KEQ1086437', self.cube.devices[0].serial) self.assertEqual(1, self.cube.devices[0].room_id) self.assertEqual('0A0881', self.cube.devices[1].rf_address) self.assertEqual('Wandthermostat', self.cube.devices[1].name) self.assertEqual(MAX_WALL_THERMOSTAT, self.cube.devices[1].type) self.assertEqual('KEQ0655743', self.cube.devices[1].serial) self.assertEqual(2, self.cube.devices[1].room_id) self.assertEqual('0CA2B2', self.cube.devices[2].rf_address) self.assertEqual('Fensterkontakt', self.cube.devices[2].name) self.assertEqual(MAX_WINDOW_SHUTTER, self.cube.devices[2].type) self.assertEqual('KEQ0839778', self.cube.devices[2].serial) self.assertEqual(1, self.cube.devices[3].room_id) self.assertEqual('Badezimmer', self.cube.rooms[0].name) self.assertEqual(1, self.cube.rooms[0].id) self.assertEqual('Wohnzimmer', self.cube.rooms[1].name) self.assertEqual(2, self.cube.rooms[1].id) def test_parse_l_message(self): device = self.cube.devices[0] self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, device.mode) self.assertEqual(None, device.actual_temperature) self.assertEqual(8.0, device.target_temperature) device = self.cube.devices[1] self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, device.mode) self.assertEqual(22.9, device.actual_temperature) self.assertEqual(8.0, device.target_temperature) device = self.cube.devices[2] self.assertEqual(False, device.is_open) def test_resolve_device_mode(self): self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, self.cube.resolve_device_mode(24)) self.assertEqual(MAX_DEVICE_MODE_MANUAL, self.cube.resolve_device_mode(25)) def test_is_thermostat(self): device = MaxDevice() device.type = MAX_CUBE self.assertEqual(False, device.is_thermostat()) device.type = MAX_THERMOSTAT self.assertEqual(True, device.is_thermostat()) device.type = MAX_THERMOSTAT_PLUS self.assertEqual(True, device.is_thermostat()) device.type = MAX_WALL_THERMOSTAT self.assertEqual(False, device.is_thermostat()) device.type = MAX_WINDOW_SHUTTER self.assertEqual(False, device.is_thermostat()) def test_is_wall_thermostat(self): device = MaxDevice() device.type = MAX_CUBE self.assertEqual(False, device.is_wallthermostat()) device.type = MAX_THERMOSTAT self.assertEqual(False, device.is_wallthermostat()) device.type = MAX_THERMOSTAT_PLUS self.assertEqual(False, device.is_wallthermostat()) device.type = MAX_WALL_THERMOSTAT self.assertEqual(True, device.is_wallthermostat()) device.type = MAX_WINDOW_SHUTTER self.assertEqual(False, device.is_wallthermostat()) def test_is_window_shutter(self): device = MaxDevice() device.type = MAX_CUBE self.assertEqual(False, device.is_windowshutter()) device.type = MAX_THERMOSTAT self.assertEqual(False, device.is_windowshutter()) device.type = MAX_THERMOSTAT_PLUS self.assertEqual(False, device.is_windowshutter()) device.type = MAX_WALL_THERMOSTAT self.assertEqual(False, device.is_windowshutter()) device.type = MAX_WINDOW_SHUTTER self.assertEqual(True, device.is_windowshutter()) def test_set_target_temperature_thermostat(self): self.cube.set_target_temperature(self.cube.devices[0], 24.5) self.assertEqual('s:AARAAAAADi66ATE=\r\n', self.cube.connection.command) self.assertEqual(24.5, self.cube.devices[0].target_temperature) def test_set_target_temperature_windowshutter(self): self.cube.set_target_temperature(self.cube.devices[2], 24.5) self.assertEqual(None, self.cube.connection.command) def test_set_mode_thermostat(self): self.cube.set_mode(self.cube.devices[0], MAX_DEVICE_MODE_MANUAL) self.assertEqual('s:AARAAAAADi66AVA=\r\n', self.cube.connection.command) self.assertEqual(MAX_DEVICE_MODE_MANUAL, self.cube.devices[0].mode) def test_set_mode_windowshutter(self): self.cube.set_mode(self.cube.devices[2], 24.5) self.assertEqual(None, self.cube.connection.command) def test_set_temperature_mode_thermostat(self): self.cube.set_temperature_mode(self.cube.devices[2], 24.5, MAX_DEVICE_MODE_BOOST) self.assertEqual(None, self.cube.connection.command) def test_get_devices(self): devices = self.cube.get_devices() self.assertEqual(3, len(devices)) def test_device_by_rf(self): device = self.cube.device_by_rf('0CA2B2') self.assertEqual('0CA2B2', device.rf_address) self.assertEqual('Fensterkontakt', device.name) self.assertEqual(MAX_WINDOW_SHUTTER, device.type) self.assertEqual('KEQ0839778', device.serial) self.assertEqual(1, device.room_id) def test_device_by_rf_negative(self): device = self.cube.device_by_rf('DEADBEEF') self.assertEqual(None, device) def test_devices_by_room(self): room = MaxRoom() room.id = 1 devices = self.cube.devices_by_room(room) self.assertEqual(2, len(devices)) def test_devices_by_room_negative(self): room = MaxRoom() room.id = 3 devices = self.cube.devices_by_room(room) self.assertEqual(0, len(devices)) def test_get_rooms(self): rooms = self.cube.get_rooms() self.assertEqual('Badezimmer', rooms[0].name) self.assertEqual(1, rooms[0].id) self.assertEqual('Wohnzimmer', rooms[1].name) self.assertEqual(2, rooms[1].id) def test_room_by_id(self): room = self.cube.room_by_id(1) self.assertEqual('Badezimmer', room.name) self.assertEqual(1, room.id) def test_room_by_id_negative(self): room = self.cube.room_by_id(3) self.assertEqual(None, room) def test_set_programme(self): self.cube.set_programme(self.cube.devices[0], "saturday", [{ 'temp': 20.5, 'until': '13:30' }, { 'temp': 18, 'until': '24:00' }]) self.assertEqual('s:AAAQAAAADi66AQBSokkgAAAAAAA=\r\n', self.cube.connection.command) def test_set_programme_already_existing_does_nothing(self): result = self.cube.set_programme(self.cube.devices[0], 'saturday', INIT_PROGRAMME_1['saturday']) self.assertEqual(result, None) self.assertEqual(self.cube.connection.command, None) def test_get_device_as_dict(self): device = self.cube.devices[0] result = device.to_dict() self.assertEqual(result['name'], 'Thermostat') self.assertEqual(result['comfort_temperature'], 21.5) self.assertEqual(result['programme']['monday'], [{ 'until': '05:30', 'temp': 8 }, { 'until': '06:30', 'temp': 21 }, { 'until': '23:55', 'temp': 8 }, { 'until': '24:00', 'temp': 8 }])
class TestMaxCube(unittest.TestCase): """ Test the Max! Cube. """ def setUp(self): self.cube = MaxCube(MaxCubeConnectionMock(INIT_RESPONSE_1)) def test_init(self): self.assertEqual('0b6475', self.cube.rf_address) self.assertEqual('Cube', self.cube.name) self.assertEqual('01.13', self.cube.firmware_version) self.assertEqual(4, len(self.cube.devices)) def test_parse_response(self): self.cube.parse_response(INIT_RESPONSE_1) self.assertEqual('0b6475', self.cube.rf_address) self.assertEqual('Cube', self.cube.name) self.assertEqual('01.13', self.cube.firmware_version) self.assertEqual(4, len(self.cube.devices)) def test_parse_c_message(self): self.cube.parse_c_message( 'C:0b6475,7QtkdQATAf9LRVEwNTY2MzM4AAsABEAAAAAAAAAAAP///////////////////////////' 'wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly93d3cubWF4LXBvcnRhbC5lbHY' 'uZGU6ODAvY3ViZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEEN' 'FU1QAAwACAAAcIA==') device = self.cube.devices[0] self.assertEqual(4.5, device.min_temperature) self.assertEqual(25.0, device.max_temperature) def test_parse_h_message(self): self.cube.parse_h_message( 'H:KEQ0566338,0b6444,0113,00000000,335b04d2,33,32,0f0c1d,101c,03,0000' ) self.assertEqual('0b6444', self.cube.rf_address) self.assertEqual('01.13', self.cube.firmware_version) def test_parse_m_message(self): self.cube.parse_m_message( 'M:00,01,VgIEAQdLaXRjaGVuBrxTAgZMaXZpbmcGvFoDCFNsZWVwaW5nCKuCBARXb3JrBrxcBAEGvF' 'NLRVEwMzM2MTA4B0tpdGNoZW4BAQa8WktFUTAzMzYxMDAGTGl2aW5nAgEIq4JLRVEwMzM1NjYyCFNs' 'ZWVwaW5nAwEGvFxLRVEwMzM2MTA0BFdvcmsEAQ==') self.assertEqual('06BC53', self.cube.devices[0].rf_address) self.assertEqual('Kitchen', self.cube.devices[0].name) self.assertEqual('06BC5A', self.cube.devices[1].rf_address) self.assertEqual('Living', self.cube.devices[1].name) self.assertEqual('08AB82', self.cube.devices[2].rf_address) self.assertEqual('Sleeping', self.cube.devices[2].name) self.assertEqual('06BC5C', self.cube.devices[3].rf_address) self.assertEqual('Work', self.cube.devices[3].name) def test_parse_l_message(self): self.cube.parse_l_message( 'L:Cwa8U/ESGAAiAAAACwa8WgkSGAAiAAAACwa8XAkSGAUiAAAACwirggMSGAUiAAAA' ) device = self.cube.devices[0] self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, device.mode) self.assertEqual(23.6, device.actual_temperature) self.assertEqual(17.0, device.target_temperature) self.cube.parse_l_message( 'L:Cwa8U/ESGQkhALMACwa8WgkSGQAhAMAACwa8XAkSGQUhALIACwirggMSGQUhAAAA' ) device = self.cube.devices[0] self.assertEqual(MAX_DEVICE_MODE_MANUAL, device.mode) self.assertEqual(17.9, device.actual_temperature) self.assertEqual(16.5, device.target_temperature) def test_resolve_device_mode(self): self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, self.cube.resolve_device_mode(24)) self.assertEqual(MAX_DEVICE_MODE_MANUAL, self.cube.resolve_device_mode(25)) def test_is_thermostat(self): device = MaxDevice() device.type = MAX_CUBE self.assertEqual(False, device.is_thermostat()) device.type = MAX_THERMOSTAT self.assertEqual(True, device.is_thermostat()) device.type = MAX_THERMOSTAT_PLUS self.assertEqual(True, device.is_thermostat()) def test_set_target_temperature(self): self.cube.set_target_temperature(self.cube.devices[0], 24.5) self.assertEqual('s:AARAAAAABrxTATE=\r\n', self.cube.connection.command) self.assertEqual(24.5, self.cube.devices[0].target_temperature) self.cube.set_target_temperature(self.cube.devices[0], 24.6) self.assertEqual(24.5, self.cube.devices[0].target_temperature)
#!/usr/bin/python from maxcube.cube import MaxCube from maxcube.connection import MaxCubeConnection from maxcube.device import \ MAX_THERMOSTAT, \ MAX_THERMOSTAT_PLUS, \ MAX_WINDOW_SHUTTER, \ MAX_WALL_THERMOSTAT, \ MAX_DEVICE_MODE_AUTOMATIC, \ MAX_DEVICE_MODE_MANUAL, \ MAX_DEVICE_MODE_VACATION, \ MAX_DEVICE_MODE_BOOST import logging cube = MaxCube(MaxCubeConnection('192.168.XXX.XXX', 62910)) for room in cube.rooms: print("Room: " + room.name) for device in cube.devices_by_room(room): print("Device: " + device.name) print("") for device in cube.devices: if device.type == MAX_THERMOSTAT: type = "MAX_THERMOSTAT" elif device.type == MAX_THERMOSTAT_PLUS: type = "MAX_THERMOSTAT_PLUS" elif device.type == MAX_WINDOW_SHUTTER: type = "MAX_WINDOW_SHUTTER" elif device.type == MAX_WALL_THERMOSTAT:
MAX_DEVICE_MODE_HOME = 4 PUBLISH_ONLY_CHANGES = 0 PUBLISH_ALL = 1 # INIT LOGGER FORMAT = '%(asctime)-15s %(levelname)s %(name)s [%(funcName)s] %(message)s' LOGFILE = "/home/pi/eq3/maxcubed.log" #logging.basicConfig(filename=LOGFILE, format=FORMAT, level=logging.DEBUG) logging.basicConfig(filename=LOGFILE, format=FORMAT, level=logging.INFO) logger = logging.getLogger(__name__) # INIT CUBE #try: cube = MaxCube(MaxCubeConnection('192.168.0.16', 62910)) #except: # logger.error("Could not initialize cube. Exiting") # exit() logger.info("Cube initialized") # INIT MQTT success = False while not success: try: client = mqtt.Client("maxcubed") success = True except: logger.warning("Could not connect to MQTT. Will retry") time.sleep(5) logger.info("MQTT initialized")
class TestMaxCube(TestCase): """ Test the Max! Cube. """ def init(self, ClassMock, responses): self.commander = ClassMock.return_value self.commander.update.return_value = responses self.cube = MaxCube("host", 1234, now=lambda: datetime(2012, 10, 22, 5, 30)) self.commander.update.assert_called_once() self.commander.update.reset_mock() self.commander.send_radio_msg.return_value = True def test_init(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_1) self.assertEqual("KEQ0566338", self.cube.serial) self.assertEqual("0b6475", self.cube.rf_address) self.assertEqual("Cube", self.cube.name) self.assertEqual("01.13", self.cube.firmware_version) self.assertEqual(4, len(self.cube.devices)) device = self.cube.devices[0] self.assertEqual(4.5, device.min_temperature) self.assertEqual(25.0, device.max_temperature) self.assertEqual("06BC53", device.rf_address) self.assertEqual("Kitchen", device.name) self.assertEqual("06BC5A", self.cube.devices[1].rf_address) self.assertEqual("Living", self.cube.devices[1].name) self.assertEqual("08AB82", self.cube.devices[2].rf_address) self.assertEqual("Sleeping", self.cube.devices[2].name) self.assertEqual("06BC5C", self.cube.devices[3].rf_address) self.assertEqual("Work", self.cube.devices[3].name) def __update(self, responses: List[Message]): self.commander.update.return_value = responses self.cube.update() self.commander.update.assert_called_once() def test_parse_auto_l_message(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_1) self.__update([LAST_STATE_MSG]) device = self.cube.devices[0] self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, device.mode) self.assertEqual(23.6, device.actual_temperature) self.assertEqual(17.0, device.target_temperature) def test_parse_manual_l_message(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_1) self.__update( [ Message.decode( b"L:Cwa8U/ESGQkhALMACwa8WgkSGQAhAMAACwa8XAkSGQUhALIACwirggMSGQUhAAAA" ) ] ) device = self.cube.devices[0] self.assertEqual(MAX_DEVICE_MODE_MANUAL, device.mode) self.assertEqual(17.9, device.actual_temperature) self.assertEqual(16.5, device.target_temperature) def test_disconnect(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_1) self.cube.disconnect() self.commander.disconnect.assert_called_once() def test_use_persistent_connection(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_1) self.commander.use_persistent_connection = True self.assertTrue(self.cube.use_persistent_connection) self.cube.use_persistent_connection = False self.assertFalse(self.commander.use_persistent_connection) def test_is_thermostat(self, _): device = MaxDevice() device.type = MAX_CUBE self.assertFalse(device.is_thermostat()) device.type = MAX_THERMOSTAT self.assertTrue(device.is_thermostat()) device.type = MAX_THERMOSTAT_PLUS self.assertTrue(device.is_thermostat()) device.type = MAX_WALL_THERMOSTAT self.assertFalse(device.is_thermostat()) device.type = MAX_WINDOW_SHUTTER self.assertFalse(device.is_thermostat()) def test_is_wall_thermostat(self, _): device = MaxDevice() device.type = MAX_CUBE self.assertFalse(device.is_wallthermostat()) device.type = MAX_THERMOSTAT self.assertFalse(device.is_wallthermostat()) device.type = MAX_THERMOSTAT_PLUS self.assertFalse(device.is_wallthermostat()) device.type = MAX_WALL_THERMOSTAT self.assertTrue(device.is_wallthermostat()) device.type = MAX_WINDOW_SHUTTER self.assertFalse(device.is_wallthermostat()) def test_is_window_shutter(self, _): device = MaxDevice() device.type = MAX_CUBE self.assertFalse(device.is_windowshutter()) device.type = MAX_THERMOSTAT self.assertFalse(device.is_windowshutter()) device.type = MAX_THERMOSTAT_PLUS self.assertFalse(device.is_windowshutter()) device.type = MAX_WALL_THERMOSTAT self.assertFalse(device.is_windowshutter()) device.type = MAX_WINDOW_SHUTTER self.assertTrue(device.is_windowshutter()) def test_set_target_temperature(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_1) self.assertTrue(self.cube.set_target_temperature(self.cube.devices[0], 24.5)) self.assertEqual(24.5, self.cube.devices[0].target_temperature) self.commander.send_radio_msg.assert_called_once() self.commander.send_radio_msg.assert_called_with("00044000000006BC530131") def test_do_not_update_if_set_target_temperature_fails(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_1) self.commander.send_radio_msg.return_value = False self.assertFalse(self.cube.set_target_temperature(self.cube.devices[0], 24.5)) self.assertEqual(21, self.cube.devices[0].target_temperature) self.commander.send_radio_msg.assert_called_once() self.commander.send_radio_msg.assert_called_with("00044000000006BC530131") def test_set_target_temperature_should_round_temperature(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_1) self.cube.set_target_temperature(self.cube.devices[0], 24.6) self.assertEqual(24.5, self.cube.devices[0].target_temperature) self.commander.send_radio_msg.assert_called_once() self.commander.send_radio_msg.assert_called_with("00044000000006BC530131") def test_set_target_temperature_is_ignored_by_windowshutter(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) self.cube.set_target_temperature(self.cube.devices[2], 24.5) self.commander.send_radio_msg.assert_not_called() def test_set_mode_thermostat(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_1) device = self.cube.devices[0] self.assertEqual(21.0, device.target_temperature) self.cube.set_mode(device, MAX_DEVICE_MODE_MANUAL) self.assertEqual(MAX_DEVICE_MODE_MANUAL, device.mode) self.commander.send_radio_msg.assert_called_once() self.commander.send_radio_msg.assert_called_with("00044000000006BC53016A") def test_init_2(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) self.assertEqual("JEQ0341267", self.cube.serial) self.assertEqual("015d2a", self.cube.rf_address) self.assertEqual("Cube", self.cube.name) self.assertEqual("01.13", self.cube.firmware_version) self.assertEqual(3, len(self.cube.devices)) device = self.cube.devices[0] self.assertEqual(21.5, device.comfort_temperature) self.assertEqual(16.5, device.eco_temperature) self.assertEqual(4.5, device.min_temperature) self.assertEqual(30.5, device.max_temperature) device = self.cube.devices[1] self.assertEqual(21.5, device.comfort_temperature) self.assertEqual(16.5, device.eco_temperature) self.assertEqual(4.5, device.min_temperature) self.assertEqual(30.5, device.max_temperature) device = self.cube.devices[2] self.assertEqual(1, device.initialized) device = self.cube.devices[0] self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, device.mode) self.assertIsNone(device.actual_temperature) self.assertEqual(8.0, device.target_temperature) device = self.cube.devices[1] self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, device.mode) self.assertEqual(22.9, device.actual_temperature) self.assertEqual(8.0, device.target_temperature) device = self.cube.devices[2] self.assertFalse(device.is_open) self.assertTrue(device.battery == MAX_DEVICE_BATTERY_LOW) def test_parse_m_message(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) self.__update( [ Message.decode( b"M:00,01,VgIEAQdLaXRjaGVuBrxTAgZMaXZpbmcGvFoDCFNsZWVwaW5nCKuCBARXb3JrBrxcBAEGvF" b"NLRVEwMzM2MTA4B0tpdGNoZW4BAQa8WktFUTAzMzYxMDAGTGl2aW5nAgEIq4JLRVEwMzM1NjYyCFNs" b"ZWVwaW5nAwEGvFxLRVEwMzM2MTA0BFdvcmsEAQ==" ), INIT_RESPONSE_2[-1], ] ) self.assertEqual("0E2EBA", self.cube.devices[0].rf_address) self.assertEqual("Thermostat", self.cube.devices[0].name) self.assertEqual(MAX_THERMOSTAT, self.cube.devices[0].type) self.assertEqual("KEQ1086437", self.cube.devices[0].serial) self.assertEqual(1, self.cube.devices[0].room_id) self.assertEqual("0A0881", self.cube.devices[1].rf_address) self.assertEqual("Wandthermostat", self.cube.devices[1].name) self.assertEqual(MAX_WALL_THERMOSTAT, self.cube.devices[1].type) self.assertEqual("KEQ0655743", self.cube.devices[1].serial) self.assertEqual(2, self.cube.devices[1].room_id) self.assertEqual("0CA2B2", self.cube.devices[2].rf_address) self.assertEqual("Fensterkontakt", self.cube.devices[2].name) self.assertEqual(MAX_WINDOW_SHUTTER, self.cube.devices[2].type) self.assertEqual("KEQ0839778", self.cube.devices[2].serial) self.assertEqual(1, self.cube.devices[2].room_id) self.assertEqual("Kitchen", self.cube.rooms[0].name) self.assertEqual(1, self.cube.rooms[0].id) self.assertEqual("Living", self.cube.rooms[1].name) self.assertEqual(2, self.cube.rooms[1].id) def test_get_devices(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) devices = self.cube.get_devices() self.assertEqual(3, len(devices)) def test_device_by_rf(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) device = self.cube.device_by_rf("0CA2B2") self.assertEqual("0CA2B2", device.rf_address) self.assertEqual("Fensterkontakt", device.name) self.assertEqual(MAX_WINDOW_SHUTTER, device.type) self.assertEqual("KEQ0839778", device.serial) self.assertEqual(1, device.room_id) def test_device_by_rf_negative(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) device = self.cube.device_by_rf("DEADBEEF") self.assertIsNone(device) def test_devices_by_room(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) room = MaxRoom() room.id = 1 devices = self.cube.devices_by_room(room) self.assertEqual(2, len(devices)) def test_devices_by_room_negative(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) room = MaxRoom() room.id = 3 devices = self.cube.devices_by_room(room) self.assertEqual(0, len(devices)) def test_get_rooms(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) rooms = self.cube.get_rooms() self.assertEqual("Badezimmer", rooms[0].name) self.assertEqual(1, rooms[0].id) self.assertEqual("Wohnzimmer", rooms[1].name) self.assertEqual(2, rooms[1].id) def test_room_by_id(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) room = self.cube.room_by_id(1) self.assertEqual("Badezimmer", room.name) self.assertEqual(1, room.id) def test_room_by_id_negative(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) room = self.cube.room_by_id(3) self.assertIsNone(room) def test_set_programme(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) self.commander.send_radio_msg.return_value = True result = self.cube.set_programme( self.cube.devices[0], "saturday", [{"temp": 20.5, "until": "13:30"}, {"temp": 18, "until": "24:00"}], ) self.assertTrue(result) self.commander.send_radio_msg.assert_called_once() self.commander.send_radio_msg.assert_called_with( "0000100000000E2EBA010052A249200000000000" ) def test_set_programme_already_existing_does_nothing(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) result = self.cube.set_programme( self.cube.devices[0], "saturday", INIT_PROGRAMME_1["saturday"] ) self.assertIsNone(result) self.commander.send_radio_msg.assert_not_called() def test_get_device_as_dict(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) device = self.cube.devices[0] result = device.to_dict() self.assertEqual(result["name"], "Thermostat") self.assertEqual(result["comfort_temperature"], 21.5) self.assertEqual( result["programme"]["monday"], [ {"until": "05:30", "temp": 8}, {"until": "06:30", "temp": 21}, {"until": "23:55", "temp": 8}, {"until": "24:00", "temp": 8}, ], ) def test_set_auto_mode_read_temp_from_program(self, ClassMock): self.init(ClassMock, INIT_RESPONSE_2) device = self.cube.devices[0] self.assertEqual(8.0, device.target_temperature) self.cube.set_mode(device, MAX_DEVICE_MODE_AUTOMATIC) self.assertEqual(21.0, device.target_temperature) self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, device.mode) self.commander.send_radio_msg.assert_called_once() self.commander.send_radio_msg.assert_called_with("0004400000000E2EBA0100")
from maxcube.cube import MaxCube from maxcube.connection import MaxCubeConnection from maxcube.device import \ MAX_THERMOSTAT, \ MAX_THERMOSTAT_PLUS, \ MAX_WINDOW_SHUTTER, \ MAX_WALL_THERMOSTAT, \ MAX_DEVICE_MODE_AUTOMATIC, \ MAX_DEVICE_MODE_MANUAL, \ MAX_DEVICE_MODE_VACATION, \ MAX_DEVICE_MODE_BOOST import logging cube = MaxCube(MaxCubeConnection('192.168.0.20', 62910)) for room in cube.rooms: print("Room: " + room.name) for device in cube.devices_by_room(room): print("Device: " + device.name) print("") for device in cube.devices: if device.type == MAX_THERMOSTAT: type = "MAX_THERMOSTAT" elif device.type == MAX_THERMOSTAT_PLUS: type = "MAX_THERMOSTAT_PLUS" elif device.type == MAX_WINDOW_SHUTTER: type = "MAX_WINDOW_SHUTTER" elif device.type == MAX_WALL_THERMOSTAT: type = "MAX_WALL_THERMOSTAT"
import os from maxcube.cube import MaxCube from maxcube.device import ( MAX_DEVICE_MODE_AUTOMATIC, MAX_DEVICE_MODE_MANUAL, MAX_THERMOSTAT, MAX_THERMOSTAT_PLUS, MAX_WALL_THERMOSTAT, MAX_WINDOW_SHUTTER, ) cube = MaxCube(os.environ.get("MAXCUBE_IP", "192.168.0.20"), 62910) print("Serial: %s" % (cube.serial)) for room in cube.rooms: print("Room: " + room.name) for device in cube.devices_by_room(room): print("Device: " + device.name) print("") for device in cube.devices: if device.type == MAX_THERMOSTAT: type = "MAX_THERMOSTAT" elif device.type == MAX_THERMOSTAT_PLUS: type = "MAX_THERMOSTAT_PLUS" elif device.type == MAX_WINDOW_SHUTTER: type = "MAX_WINDOW_SHUTTER" elif device.type == MAX_WALL_THERMOSTAT: type = "MAX_WALL_THERMOSTAT"
print(i['Name'] + " has a idx " + i['idx']) domoticz_props[i['Name']] = [i['idx'], i['LastUpdate'], i['Data']] #searching for -Sens url = "http://" + DOMOTICZ_IP + ":" + DOMOTICZ_PORT + "/json.htm?type=devices&filter=temp&used=true&order=Name" response = urllib.urlopen(url) data = json.loads(response.read()) for i in data['result']: if i['Name'][-5:] == "-Sens": #print (i['Name'] + " has a idx " + i['idx'] + " last updated " + i['LastUpdate']) domoticz_props[i['Name']] = [i['idx'], i['LastUpdate'], i['Data']] cube = MaxCube(MaxCubeConnection(IP_CUBE, PORT_CUBE)) for device in cube.devices: if device.type != MAX_THERMOSTAT: print("Not a thermostat ommiting this device") else: print("Updating Termostat: " + device.name + 'Read valve open: ' + str(device.valve_position) + ' Read temperature: ' + str(device.actual_temperature)) #updating domoticz with the read value search_name = device.name[0:-5].encode('ascii', 'ignore') url = "http://" + DOMOTICZ_IP + ":" + DOMOTICZ_PORT + "/json.htm?type=command¶m=udevice&idx=" + domoticz_props[ search_name + '-Rad'][0] + "&nvalue=0&svalue=" + str( device.valve_position) response = urllib.urlopen(url) if str(device.actual_temperature) != "None":
def __init__(self, address, port): # connect to the cube self.cube = MaxCube(MaxCubeConnection(address, port))
class TestMaxCube(unittest.TestCase): """ Test the Max! Cube. """ def setUp(self): self.cube = MaxCube(MaxCubeConnectionMock()) def test_init(self): self.assertEqual('0b6475', self.cube.rf_address) self.assertEqual('Cube', self.cube.name) self.assertEqual('01.13', self.cube.firmware_version) self.assertEqual(4, len(self.cube.devices)) def test_parse_response(self): self.cube.parse_response(INIT_RESPONSE) self.assertEqual('0b6475', self.cube.rf_address) self.assertEqual('Cube', self.cube.name) self.assertEqual('01.13', self.cube.firmware_version) self.assertEqual(4, len(self.cube.devices)) def test_parse_c_message(self): self.cube.parse_c_message('C:0b6475,7QtkdQATAf9LRVEwNTY2MzM4AAsABEAAAAAAAAAAAP///////////////////////////' 'wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly93d3cubWF4LXBvcnRhbC5lbHY' 'uZGU6ODAvY3ViZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEEN' 'FU1QAAwACAAAcIA==') device = self.cube.devices[0] self.assertEqual(4.5, device.min_temperature) self.assertEqual(25.0, device.max_temperature) def test_parse_h_message(self): self.cube.parse_h_message('H:KEQ0566338,0b6444,0113,00000000,335b04d2,33,32,0f0c1d,101c,03,0000') self.assertEqual('0b6444', self.cube.rf_address) self.assertEqual('01.13', self.cube.firmware_version) def test_parse_m_message(self): self.cube.parse_m_message('M:00,01,VgIEAQdLaXRjaGVuBrxTAgZMaXZpbmcGvFoDCFNsZWVwaW5nCKuCBARXb3JrBrxcBAEGvF' 'NLRVEwMzM2MTA4B0tpdGNoZW4BAQa8WktFUTAzMzYxMDAGTGl2aW5nAgEIq4JLRVEwMzM1NjYyCFNs' 'ZWVwaW5nAwEGvFxLRVEwMzM2MTA0BFdvcmsEAQ==') self.assertEqual('6BC53', self.cube.devices[0].rf_address) self.assertEqual('Kitchen', self.cube.devices[0].name) self.assertEqual('6BC5A', self.cube.devices[1].rf_address) self.assertEqual('Living', self.cube.devices[1].name) self.assertEqual('8AB82', self.cube.devices[2].rf_address) self.assertEqual('Sleeping', self.cube.devices[2].name) self.assertEqual('6BC5C', self.cube.devices[3].rf_address) self.assertEqual('Work', self.cube.devices[3].name) def test_parse_l_message(self): self.cube.parse_l_message('L:Cwa8U/ESGAAiAAAACwa8WgkSGAAiAAAACwa8XAkSGAUiAAAACwirggMSGAUiAAAA') device = self.cube.devices[0] self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, device.mode) self.assertEqual(23.6, device.actual_temperature) self.assertEqual(17.0, device.target_temperature) self.cube.parse_l_message('L:Cwa8U/ESGQkhALMACwa8WgkSGQAhAMAACwa8XAkSGQUhALIACwirggMSGQUhAAAA') device = self.cube.devices[0] self.assertEqual(MAX_DEVICE_MODE_MANUAL, device.mode) self.assertEqual(17.9, device.actual_temperature) self.assertEqual(16.5, device.target_temperature) def test_resolve_device_mode(self): self.assertEqual(MAX_DEVICE_MODE_AUTOMATIC, self.cube.resolve_device_mode(24)) self.assertEqual(MAX_DEVICE_MODE_MANUAL, self.cube.resolve_device_mode(25)) def test_is_thermostat(self): device = MaxDevice() device.type = MAX_CUBE self.assertEqual(False, self.cube.is_thermostat(device)) device.type = MAX_THERMOSTAT self.assertEqual(True, self.cube.is_thermostat(device)) device.type = MAX_THERMOSTAT_PLUS self.assertEqual(True, self.cube.is_thermostat(device)) def test_set_target_temperature(self): self.cube.set_target_temperature(self.cube.devices[0], 24.5) self.assertEqual('s:AARAAAAABrxTATE=\r\n', self.cube.connection.command) self.assertEqual(24.5, self.cube.devices[0].target_temperature) self.cube.set_target_temperature(self.cube.devices[0], 24.6) self.assertEqual(24.5, self.cube.devices[0].target_temperature)
def setUp(self): self.cube = MaxCube(MaxCubeConnectionMock())
def setUp(self): self.cube = MaxCube(MaxCubeConnectionMock())
class Controller: def __init__(self, address, port): # connect to the cube self.cube = MaxCube(MaxCubeConnection(address, port)) # setup the output mode on all the pins wiringpi.wiringPiSetup() wiringpi.pinMode(PIN1, 1) wiringpi.pinMode(PIN2, 1) wiringpi.pinMode(PIN3, 1) # pin_status dict contains the current status of the output pins # status 0 means that the pump is operating normally (turned on) # status 1 means that the pump is turned off (1 on the GPIO pin opens the relay) self.pin_status = {PIN1: 0, PIN2: 0, PIN3: 0} # map apartment IDs to the output pins self.pin_mapping = {"10": PIN1, "11": PIN2} def update_pins(self): """ update the GPIO pins to the status set in the self.pin_status dictionary """ for pin in [PIN1, PIN2, PIN3]: wiringpi.digitalWrite(pin, self.pin_status[pin]) def scan_and_update_pins(self): """ Scan for all the connected thermostats. They are named "ID_name", where ID is the id of the apartment. If valves on all the thermostats in an apartment are set to 0, turn off the corresponding pin """ self.cube.update() apartments = {} print(len(self.cube.devices), "devices found") for device in self.cube.devices: id = device.name.split("_")[0] if id not in apartments: apartments[id] = [] apartments[id].append(device) for id in apartments.keys(): all_off = True for device in apartments[id]: all_off &= device.valve_position == 0 if all_off: if self.pin_status[self.pin_mapping[id]] == 0: print("The pump for apartment", id, "will be turned off.") self.pin_status[self.pin_mapping[id]] = 1 else: if self.pin_status[self.pin_mapping[id]] == 1: print("The pump for apartment", id, "will be turned back on.") self.pin_status[self.pin_mapping[id]] = 0 self.update_pins() def run_forever(self, interval=5): while True: try: self.scan_and_update_pins() sleep(interval * 60) except Exception: print("Background sleep was terminated, exiting the loop") break # turn everything to 0 and exit wiringpi.wiringPiSetup() wiringpi.pinMode(PIN1, 1) wiringpi.pinMode(PIN2, 1) wiringpi.pinMode(PIN3, 1) wiringpi.digitalWrite(PIN1, 0) wiringpi.digitalWrite(PIN2, 0) wiringpi.digitalWrite(PIN3, 0) print("All the pumps are now on") print("Controller is shutting down")