Beispiel #1
0
    def writeGroupsToDali(self, dali):
        logger.info("Writing group stuff to DALI-device")

        # Remark: Non named groups from file will be left untouched nor will be
        # deleted from devices.
        for deviceShortAddr in self.data["devices"].keys():
            logging.debug("Device %u: Query for groupmask" % (deviceShortAddr))
            # Get group info may speedup setting things later on.
            grp = d.send(QueryGroupsZeroToSeven(deviceShortAddr))
            grp2 = d.send(QueryGroupsEightToFifteen(deviceShortAddr))
            groupMask = grp2.value.as_integer << 8 | grp.value.as_integer
            logging.debug("Device %u: Groupmask: 0x%x" %
                          (deviceShortAddr, groupMask))

            for groupId in range(16):
                currentlyMemberOfGroup = (groupMask & (1 << groupId)) != 0
                memberOfGroup = groupId in self.data[
                    "groups"] and deviceShortAddr in self.data["groups"][
                        groupId]
                # logging.debug("Device %u / group %u: member: %r, newMember: %r"%(deviceShortAddr,groupId,currentlyMemberOfGroup,memberOfGroup))
                if memberOfGroup != currentlyMemberOfGroup:
                    logging.debug(
                        "Device %u: Correcting group (%u) assignment" %
                        (deviceShortAddr, groupId))
                    if memberOfGroup:
                        dali.send(AddToGroup(Short(deviceShortAddr), groupId))
                    else:
                        dali.send(
                            RemoveFromGroup(Short(deviceShortAddr), groupId))
        logger.info("Writing group stuff to DALI-device was successful")
Beispiel #2
0
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the DALI Light platform."""

    from dali.driver.hasseb import SyncHassebDALIUSBDriver 
    from dali.address import Short
    from dali.command import YesNoResponse, Response
    import dali.gear.general as gear

    dali_driver = SyncHassebDALIUSBDriver() 
    import threading
    lock = threading.RLock()

    lamps = []
    for lamp in range(0,config[CONF_MAX_GEARS]):
        try:
            _LOGGER.debug("Searching for Gear on address <{}>".format(lamp))
            r = dali_driver.send(gear.QueryControlGearPresent(Short(lamp)))
            if isinstance(r, YesNoResponse) and r.value:
                lamps.append(Short(lamp))
        except Exception as e:
            #Not present
            _LOGGER.error("Error while QueryControlGearPresent: {}".format(e))
            break

    add_devices([DALILight(dali_driver, lock, config[CONF_NAME], l) for l in lamps])
Beispiel #3
0
    def __init__(self, driver, driver_lock, ballast):
        from dali.address import Short
        from dali.gear.general import QueryStatus
        from dali.gear.general import QueryStatusResponse
        from dali.gear.general import DTR0
        from dali.gear.general import QueryPowerOnLevel
        from dali.gear.general import QueryLampPowerOn
        """Initialize a DALI Light."""
        self._id = ballast['id']
        self._name = ballast['name']
        self._brightness = 0
        self._state = False

        self.driver = driver
        self.driver_lock = driver_lock
        self.addr = Short(int(self._id))

        with self.driver_lock:
            cmd = QueryPowerOnLevel(self.addr)
            r = self.driver.send(cmd)
            if r.value != None:
                self._brightness = to_hass_level(r.value.as_integer)

        with self.driver_lock:
            cmd = QueryLampPowerOn(self.addr)
            r = self.driver.send(cmd)
            if r.value != None:
                self._state = r.value
Beispiel #4
0
    def writeScenesToDali(self, dali):
        for (sceneId, sceneContent) in self.data["scenes"].iteritems():
            logging.debug("Working on Scene %u" % (sceneId))
            for deviceShortAddr in self.data["devices"].keys():
                sceneValue = None
                if deviceShortAddr in sceneContent:
                    sceneValue = sceneContent[deviceShortAddr]
                elif "default" in sceneContent:
                    sceneValue = sceneContent["default"]

                if sceneValue is not None:
                    logging.debug("Device %u: Set scene level to %u" %
                                  (deviceShortAddr, sceneValue))
                    dali.send(DTR0(sceneValue))
                    dali.send(SetScene(deviceShortAddr, sceneId))
                    r = dali.send(QuerySceneLevel(deviceShortAddr, sceneId))
                    if r.value.as_integer != sceneValue:
                        logging.error(
                            "Device %u: Set scene level to %u FAILED (query retrieves: %u)"
                            %
                            (deviceShortAddr, sceneValue, r.value.as_integer))
                else:
                    logging.debug("Device %u: Remove from scene" %
                                  (deviceShortAddr))
                    dali.send(RemoveFromScene(Short(deviceShortAddr), sceneId))
Beispiel #5
0
 def __init__(self, address, name=None, bus=None):
     if not isinstance(address, int) or address < 0 or address > 63:
         raise ValueError("address must be an integer in the range 0..63")
     self.address = address
     self._addressobj = Short(address)
     self.bus = None
     if bus:
         self.bind(bus)
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the DALI Light platform."""

    from dali.address import Short
    from dali.command import YesNoResponse, Response
    import dali.gear.general as gear
    from dali.driver.hasseb import SyncHassebDALIUSBDriverFactory
    from dali.driver.hasseb import SyncHassebDALIUSBDriver
    import threading

    dali_drivers = SyncHassebDALIUSBDriverFactory()

    for idx, dali_driver in enumerate(dali_drivers):
        _LOGGER.debug("Found DALI driver")
        lock = threading.RLock()

        driver_config = config[CONF_DRIVERS][idx]

        lamps = []
        for lamp in range(0, driver_config[CONF_MAX_GEARS]):
            try:  # @TODO initialize new gears
                _LOGGER.debug(
                    "Searching for Gear on address <{}>".format(lamp))
                r = dali_driver.send(gear.QueryControlGearPresent(Short(lamp)))

                if isinstance(r, YesNoResponse) and r.value:
                    _LOGGER.debug("Found lamp!")
                    lamps.append(Short(lamp))

            except Exception as e:
                # This will often mean that the driver wasn't found
                _LOGGER.error(
                    "Error while QueryControlGearPresent: {}".format(e))
                _LOGGER.error("Hasseb DALI master not found")
                break

        add_devices([
            DALILight(dali_driver, lock, driver_config[CONF_NAME], l, idx)
            for l in lamps
        ])
        add_devices([
            DALIBus(dali_driver, lock, driver_config[CONF_NAME], lamps,
                    config[CONF_MAX_BUSES], idx)
        ])
Beispiel #7
0
def QueryDT1(d, addr):
    from dali.gear.emergency import QueryEmergencyFailureStatus
    from dali.gear.emergency import QueryEmergencyFeatures
    from dali.gear.emergency import QueryEmergencyMode
    from dali.gear.emergency import QueryEmergencyStatus

    d.send(EnableDeviceType(1))
    r = d.send(QueryEmergencyMode(Short(addr)))
    logging.info(" -- {0}".format(r))

    d.send(EnableDeviceType(1))
    r = d.send(QueryEmergencyFeatures(Short(addr)))
    logging.info(" -- {0}".format(r))

    d.send(EnableDeviceType(1))
    r = d.send(QueryEmergencyFailureStatus(Short(addr)))
    logging.info(" -- {0}".format(r))

    d.send(EnableDeviceType(1))
    r = d.send(QueryEmergencyStatus(Short(addr)))
    logging.info(" -- {0}".format(r))
Beispiel #8
0
        def enter_interactive_mode(self):
            # First program a free short address and remember it
            if self.nextShortAddress in self.assignedAddresses:
                for i in xrange(63, -1, -1):
                    if i not in self.assignedAddresses:
                        self.nextShortAddress = i
                        break

            self.ifc.send(ProgramShortAddress(self.nextShortAddress))

            while True:
                print(
                    "Enter number to assign to flashing ballast or press enter to flash again: "
                )
                # Flash the ballast
                time.sleep(1)
                self.ifc.send(DAPC(Short(self.nextShortAddress), 0))
                time.sleep(1)
                self.ifc.send(DAPC(Short(self.nextShortAddress), 254))

                try:
                    newAddress = int(raw_input())
                except:
                    continue

                if newAddress < 0 or newAddress >= 64:
                    print("ERROR: Out of range")
                    continue
                if newAddress in self.assignedAddresses:
                    print("ERROR: Address already chosen")
                    continue

                self.ifc.send(ProgramShortAddress(newAddress))

                # It seems to be quite enough to set the address again.
                #self.ifc.send(DTR0(newAddress<<1 | 0x01))
                #self.ifc.send(SetShortAddress(Short(self.nextShortAddress) ))
                self.assignedAddresses.append(newAddress)
                return newAddress
Beispiel #9
0
 def __init__(self,
              address,
              randomAddress=None,
              deviceType=None,
              groups=None,
              bus=None):
     if not isinstance(address, int) or address < 0 or address > 63:
         print("Address must be an integer in the range 0..63")
     self.address = address
     self.address_obj = Short(address)
     self.bus = None
     if bus:
         self.bind(bus)
     self.randomAddress = randomAddress
     self.deviceType = deviceType
     self.groups = groups
Beispiel #10
0
def QueryDT6(d, addr):
    from dali.gear.led import QueryFeatures
    from dali.gear.led import QueryGearType
    from dali.gear.led import QueryOperatingMode
    from dali.gear.led import QueryFailureStatus
    from dali.gear.led import QueryFastFadeTime
    from dali.gear.led import QueryMinFastFadeTime
    from dali.gear.led import QueryDimmingCurve

    d.send(EnableDeviceType(6))
    r = d.send(QueryFeatures(Short(addr)))
    logging.info(" -- {0}".format(r))

    d.send(EnableDeviceType(6))
    r = d.send(QueryGearType(Short(addr)))
    logging.info(" -- {0}".format(r))

    d.send(EnableDeviceType(6))
    r = d.send(QueryOperatingMode(Short(addr)))
    logging.info(" -- {0}".format(r))

    d.send(EnableDeviceType(6))
    r = d.send(QueryFailureStatus(Short(addr)))
    logging.info(" -- {0}".format(r))

    d.send(EnableDeviceType(6))
    r = d.send(QueryFastFadeTime(Short(addr)))
    logging.info(" -- {0}".format(r))

    d.send(EnableDeviceType(6))
    r = d.send(QueryMinFastFadeTime(Short(addr)))
    logging.info(" -- {0}".format(r))

    d.send(EnableDeviceType(6))
    r = d.send(QueryDimmingCurve(Short(addr)))
    logging.info(" -- {0}".format(r))
Beispiel #11
0
 def test_construct_length_16(self):
     driver = UnipiDALIDriver()
     command = DAPC(Short(1), 2)
     self.assertEqual(driver.construct(command), (512, 514))
Beispiel #12
0
    import signal
    import sys
    import time

    # setup console logging
    logger = logging.getLogger('UnipiDALIDriver')
    #logger.setLevel(logging.DEBUG)
    handler = logging.StreamHandler(sys.stdout)
    handler.setLevel(logging.DEBUG)
    handler.setFormatter(
        logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
    logger.addHandler(handler)

    # sync interface
    addr = Short(int(sys.argv[1]))
    # command to send
    #command = DAPC(addr, int(sys.argv[2]))
    #_test_sync(logger, command)
    command = QueryStatus(addr)
    _test_sync(logger, command)
    command = QueryDeviceType(addr)
    _test_sync(logger, command)
    #command = QueryLightSourceType(addr)
    #_test_sync(logger, command)
    command = QueryActualLevel(addr)
    _test_sync(logger, command)
    #command = RecallMaxLevel(addr)
    #command = RecallMinLevel(addr)
    command = Off(addr)
    _test_sync(logger, command)
Beispiel #13
0
#!/usr/bin/env python

from dali.address import Broadcast
from dali.address import Short
from dali.gear.general import DAPC
from dali.interface import DaliServer
import sys

if __name__ == "__main__":
    addr = Short(int(sys.argv[1])) if sys.argv[1] != "all" else Broadcast()
    level = int(sys.argv[2])
    d = DaliServer("localhost", 55825)
    cmd = DAPC(addr, level)
    d.send(cmd)
Beispiel #14
0
from dali.address import Short
from dali.gear.general import EnableDeviceType
from dali.gear.general import QueryDeviceType
from dali.gear.emergency import QueryEmergencyFailureStatus
from dali.gear.emergency import QueryEmergencyFeatures
from dali.gear.emergency import QueryEmergencyMode
from dali.gear.emergency import QueryEmergencyStatus
from dali.driver.launchpad_lw14 import LAUNCHPAD_LED_WARRIOR_14
import logging

if __name__ == "__main__":
    log_format = '%(levelname)s: %(message)s'
    logging.basicConfig(format=log_format, level=logging.DEBUG)
    d = LAUNCHPAD_LED_WARRIOR_14(port='/dev/ttyACM0')
    for addr in range(0, 64):
        cmd = QueryDeviceType(Short(addr))
        r = d.send(cmd)

        logging.info("[%d]: resp: %s" % (addr, r))

        if r.value == 1:
            d.send(EnableDeviceType(1))
            r = d.send(QueryEmergencyMode(Short(addr)))
            logging.info(" -- {0}".format(r))

            d.send(EnableDeviceType(1))
            r = d.send(QueryEmergencyFeatures(Short(addr)))
            logging.info(" -- {0}".format(r))

            d.send(EnableDeviceType(1))
            r = d.send(QueryEmergencyFailureStatus(Short(addr)))
Beispiel #15
0
    d.send(EnableDeviceType(6))
    r = d.send(QueryDimmingCurve(Short(addr)))
    logging.info(" -- {0}".format(r))


def QueryDT8(d, addr):
    pass


if __name__ == "__main__":
    log_format = '%(levelname)s: %(message)s'
    logging.basicConfig(format=log_format, level=logging.DEBUG)

    with DaliServer() as d:
        for addr in range(0, 64):
            cmd = QueryDeviceType(Short(addr))
            r = d.send(cmd)

            logging.info("[%d]: resp: %s" % (addr, r))

            if r.value is not None:
                if r.value.as_integer == 255:
                    while True:
                        cmd = QueryNextDeviceType(Short(addr))
                        r = d.send(cmd)
                        if r.value is not None and r.value != 254:
                            QueryGear(d, r.value.as_integer, addr)
                        else:
                            break
                else:
                    QueryGear(d, r.value.as_integer, addr)
Beispiel #16
0
def Commissioning(available_addresses=None, readdress=False, dry_run=False):
    """Assign short addresses to control gear

    If available_addresses is passed, only the specified addresses
    will be assigned; otherwise all short addresses are considered to
    be available.

    if "readdress" is set, all existing short addresses will be
    cleared; otherwise, only control gear that is currently
    unaddressed will have short addresses assigned.

    If "dry_run" is set then no short addresses will actually be set.
    This can be useful for testing.
    """
    if available_addresses is None:
        available_addresses = list(range(64))
    else:
        available_addresses = list(available_addresses)

    if readdress:
        if dry_run:
            yield progress(message="dry_run is set: not deleting existing "
                           "short addresses")
        else:
            yield DTR0(255)
            yield SetShortAddress(Broadcast())
    else:
        # We need to know which short addresses are already in use
        for a in range(0, 64):
            if a in available_addresses:
                in_use = yield QueryControlGearPresent(Short(a))
                if in_use.value:
                    available_addresses.remove(a)
        yield progress(message=f"Available addresses: {available_addresses}")

    yield Terminate()
    yield Initialise(broadcast=True if readdress else False)

    finished = False
    # We loop here to cope with multiple devices picking the same
    # random search address; when we discover that, we
    # re-randomise and begin again.  Devices that have already
    # received addresses are unaffected.
    while not finished:
        yield Randomise()
        # Randomise can take up to 100ms
        yield sleep(0.1)

        low = 0
        high = 0xffffff

        while low is not None:
            yield progress(completed=low, size=high)
            low = yield from _find_next(low, high)
            if low == "clash":
                yield progress(message="Multiple ballasts picked the same "
                               "random address; restarting")
                break
            if low is None:
                finished = True
                break
            yield progress(message=f"Ballast found at address {low:#x}")
            if available_addresses:
                new_addr = available_addresses.pop(0)
                if dry_run:
                    yield progress(message="Not programming short address "
                                   f"{new_addr} because dry_run is set")
                else:
                    yield progress(
                        message=f"Programming short address {new_addr}")
                    yield ProgramShortAddress(new_addr)
                    r = yield VerifyShortAddress(new_addr)
                    if r.value is not True:
                        raise ProgramShortAddressFailure(new_addr)
            else:
                yield progress(
                    message="Device found but no short addresses left")
            yield Withdraw()
            if low < high:
                low = low + 1
            else:
                low = None
                finished = True
    yield Terminate()
    yield progress(message="Addressing complete")
Beispiel #17
0
 def test_construct_length_16_config(self):
     driver = UnipiDALIDriver()
     command = Reset(Short(1))
     self.assertEqual(driver.construct(command), (2560, 800))
Beispiel #18
0
async def main(args, loop):
    driver = drivers[args.driver]
    d = driver(args.device, loop=loop)
    if args.debug:
        d.bus_traffic.register(print_command_and_response)
    if not d.connect():
        log.error("Unable to open device %s with %s driver", args.device,
                  args.driver)
        d.disconnect()
        return
    await d.connected.wait()
    log.info("Connected to device %s with %s driver", args.device, args.driver)

    available_addresses = list(range(0, 64))
    if args.mode != "readdress":
        # Work out which short addresses are in use
        for a in range(0, 64):
            in_use = await d.send(QueryControlGearPresent(Short(a)))
            if in_use.value:
                available_addresses.remove(a)

    log.info("Addresses available for allocation: %s", available_addresses)

    if args.mode == "readdress":
        if args.dry_run:
            log.info("Not deleting existing addresses because --dry-run")
        else:
            await d.send(DTR0(255))
            await d.send(SetShortAddress(Broadcast()))

    await d.send(Terminate())
    await d.send(
        Initialise(broadcast=True if args.mode == "readdress" else False))
    await d.send(Randomise())
    # Randomise can take up to 100ms
    await asyncio.sleep(0.1)
    low = 0
    high = 0xffffff
    while low is not None:
        low = await find_next(d, low, high)
        if low is not None:
            if available_addresses:
                new_addr = available_addresses.pop(0)
                if args.dry_run:
                    log.info(
                        "Not programming short address %s because --dry-run",
                        new_addr)
                else:
                    log.info("Programming short address %s", new_addr)
                    await d.send(ProgramShortAddress(new_addr))
                    r = await d.send(VerifyShortAddress(new_addr))
                    if r.value is not True:
                        log.error("Device did not accept short address %s",
                                  new_addr)
            else:
                log.info("Device found but no short addresses remaining")
            await d.send(Withdraw())
            low = low + 1
    await d.send(Terminate())
    log.info("Addressing complete")
    d.disconnect()