Example #1
0
class GameVoice(eg.PluginClass):
    def __init__(self):
        self.thread = None

    def ButtonCallback(self, data):
        btnPressed = []
        for num in data:
            btnPressed.append(ButtonMapping[num])

        buttonsCount = len(btnPressed)
        if buttonsCount == 0:
            self.TriggerEvent("None")
        elif buttonsCount == 1:
            self.TriggerEvent(btnPressed[0])
        else:
            self.TriggerEvent("+".join(btnPressed))

    def StopCallback(self):
        self.TriggerEvent("Stopped")
        self.thread = None

    def GetMyDevicePath(self):
        path = GetDevicePath(None, VENDOR_ID, PRODUCT_ID, None, 0, True, 0)
        return path

    def SetupHidThread(self, newDevicePath):
        #create thread
        self.thread = HIDThread(self.name, newDevicePath, self.name)
        self.thread.start()
        self.thread.SetStopCallback(self.StopCallback)
        self.thread.SetButtonCallback(self.ButtonCallback)

    def SetFeature(self, buffer):
        if self.thread:
            self.thread.SetFeature(buffer)

    def ReconnectDevice(self, event):
        """method to reconnect a disconnect device"""
        if self.thread == None:
            if not IsDeviceName(event.payload, VENDOR_ID, PRODUCT_ID):
                return

            #check if the right device was connected
            #getting devicePath
            newDevicePath = self.GetMyDevicePath()
            if not newDevicePath:
                #wrong device
                return

            self.SetupHidThread(newDevicePath)

    def __start__(self):
        #Bind plug in to RegisterDeviceNotification message
        eg.Bind("System.DeviceAttached", self.ReconnectDevice)

        newDevicePath = self.GetMyDevicePath()
        if not newDevicePath:
            #device not found
            self.PrintError(Text.errorFind)
        else:
            self.SetupHidThread(newDevicePath)

    def __stop__(self):
        if self.thread:
            self.thread.AbortThread()

        #unbind from RegisterDeviceNotification message
        eg.Unbind("System.DeviceAttached", self.ReconnectDevice)
class HIDPS3(eg.PluginClass):
    def __init__(self):
        self.text = Text
        self.thread = None
        self.PS3Remote = PS3Remote
        self.batteryLevel = None
        self.AddAction(GetBatteryLevel)

    def RawCallback(self, data):
        #hexdata= binascii.hexlify(data).upper()
        #eg.PrintNotice( hexdata )

        try:
            if len(data) != 12:
                raise PS3ParseError( 'length', 12, len(data) )

            start= ord( data[0] )
            mask= ord( data[1] )<<16 | ord( data[2] )<<8 | ord( data[3] )
            code= ord( data[4] )
            dummy= data[5:10]
            state= ord( data[10] )
            battery= ord( data[11] )

            if start != 0x01:
                raise PS3ParseError( 'data[0]', '0x01', hex(start) )

            if dummy != "\xff\xff\xff\xff\xff":
                raise PS3ParseError( 'data[5:10]', '0xffffffffff', hex(dummy) )

            if battery > 0x05:
                raise PS3ParseError( 'battery level', '0-5', battery )

            if( battery < 0x02 ):
                eg.PrintNotice(
                    'PS3 Remote: Battery Level: ' +
                        self.text.batteryLevel[battery]
                )

            #self.TriggerEvent(
            #    'Code: ' + hex(code) +
            #        ' State: ' + hex(state) +
            #        ' Battery Level: ' + str(battery) + ':' +
            #        self.text.batteryLevel[battery] +
            #        '  Mask: ' + bin(mask),
            #    payload= ( battery, self.text.batteryLevel[battery] )
            #)

            if( code != 0xff and code not in self.PS3Remote.button ):
                raise PS3ParseError( 'Key code', 'various', hex(code) )

            btnPressed = []

            if( code != 0xff ):
                # single button pressed
                btnPressed.append( self.PS3Remote.button[code] )
            else:
                # multiple buttons pressed
                if( mask != 0x00 ):
                    for bit in range( 24 ):
                        if( mask & 1<<bit ):
                            if( bit not in self.PS3Remote.maskbit ):
                                PS3ParseError( 'Mask', 'various', bin(mask) )
                            btnPressed.append( self.PS3Remote.maskbit[bit] )
                    if btnPressed == []:
                        PS3ParseError( 'Mask', 'various','Empty Mask' )

            if btnPressed != []:
                evtName = 'Button.' + '+'.join(btnPressed)
                if self.enduringEvents:
                    self.TriggerEnduringEvent(evtName)
                else:
                    self.TriggerEvent(evtName)
            elif self.enduringEvents:
                #no buttons pressed anymore
                self.EndLastEvent()
            elif self.ps3Release:
                #trigger event so that releasing all buttons
                #can get noticed even w/o enduring events
                self.TriggerEvent( 'Button.None' )

            self.batteryLevel= battery

        except PS3ParseError as catchedError:
            eg.PrintError(
                'PS3-HID Plugin: ' + catchedError +
                '  Data: 0x' + binascii.hexlify(data).lower()
            )

    def StopCallback(self):
        self.TriggerEvent("Stopped")
        self.thread = None

    def GetMyDevicePath(self):
        path = GetDevicePath(
            self.devicePath,
            self.vendorID,
            self.productID,
            self.versionNumber,
            self.useDeviceIndex,
            self.deviceIndex,
            self.noOtherPort)
        return path;

    def SetupHidThread(self, newDevicePath):
        #create thread
        self.thread = HIDThread(
            self.vendorString + " " + self.productString, newDevicePath
        )
        self.thread.start()
        self.thread.SetStopCallback(self.StopCallback)
        self.thread.SetRawCallback(self.RawCallback)

    def ReconnectDevice(self, event):
        """method to reconnect a disconnect device"""
        if self.thread == None:
            #updating device list

            #check if the right device was connected
            #getting devicePath
            newDevicePath = self.GetMyDevicePath()
            if not newDevicePath:
                #wrong device
                return

            self.SetupHidThread(newDevicePath)

    def GetLabel(self,
        eventName,
        enduringEvents,
        rawDataEvents,
        ps3DataEvents,
        ps3Release,
        ps3Zone,
        shortKeyTime,
        longKeyTime,
        sleepTime,
        hibernateTime,
        noOtherPort,
        devicePath,
        vendorID,
        vendorString,
        productID,
        productString,
        versionNumber,
        # For backwards-compatibility with 2.0.2 and 3.0.0 - if a new config option is added this can just be replaced
        dummy = None,
        useDeviceIndex = False,
        deviceIndex = 0
    ):
        prefix = "PS3: "
        #one or both strings empty should not happen
        if not vendorString or not productString:
            return "PS3"

        #productString already contains manufacturer or vendor id only
        if productString.find(vendorString) != -1 or\
            vendorString[0:len(self.text.vendorID)] == self.text.vendorID:
            return prefix + productString

        return prefix + vendorString + " " + productString

    def __start__(self,
        eventName,
        enduringEvents,
        rawDataEvents,
        ps3DataEvents,
        ps3Release,
        ps3Zone,
        shortKeyTime,
        longKeyTime,
        sleepTime,
        hibernateTime,
        noOtherPort,
        devicePath,
        vendorID,
        vendorString,
        productID,
        productString,
        versionNumber,
        # For backwards-compatibility with 2.0.2 and 3.0.0 - if a new config option is added this can just be replaced
        dummy = None,
        useDeviceIndex = False,
        deviceIndex = 0
    ):

        #saving parameters so they can be used to reconnect a device
        self.eventName = eventName
        self.enduringEvents = enduringEvents
        self.noOtherPort = noOtherPort
        self.devicePath = devicePath
        self.vendorID = vendorID
        self.vendorString = vendorString
        self.productID = productID
        self.productString = productString
        self.versionNumber = versionNumber
        self.useDeviceIndex = useDeviceIndex
        self.deviceIndex = deviceIndex
        self.ps3Release = ps3Release
        self.oldValues = {}

        if eventName:
            self.info.eventPrefix = eventName
        else:
            self.info.eventPrefix = "PS3"

        #Bind plug in to RegisterDeviceNotification message
        eg.Bind("System.DeviceAttached", self.ReconnectDevice)

        newDevicePath = self.GetMyDevicePath()
        if not newDevicePath:
            #device not found
            self.PrintError(Text.errorFind)
        else:
            self.SetupHidThread(newDevicePath)

    def __stop__(self):
        if self.thread:
            self.thread.AbortThread()

        #unbind from RegisterDeviceNotification message
        eg.Unbind("System.DeviceAttached", self.ReconnectDevice)

    def Configure(self,
        eventName = "",
        enduringEvents = True,
        rawDataEvents = False, # no longer used
        ps3DataEvents = False, # no longer used
        ps3Release = False,
        ps3Zone = False, # no longer used
        shortKeyTime = 0.0, # no longer used
        longKeyTime = 0.0, # no longer used
        sleepTime = 5.0,
        hibernateTime = 60.0,
        noOtherPort = False,
        devicePath = None,
        vendorID = None,
        vendorString = None,
        productID = None,
        productString = None,
        versionNumber = None,
        # For backwards-compatibility with 2.0.2 and 3.0.0 - if a new config option is added this can just be replaced
        dummy = None,
        useDeviceIndex = False,
        deviceIndex = 0
    ):
        deviceList = GetDeviceDescriptions()
        panel = eg.ConfigPanel(self, resizable=True)

        #building dialog
        hidList = wx.ListCtrl(panel, -1, pos=wx.DefaultPosition,
            size=wx.DefaultSize, style=wx.LC_REPORT | wx.LC_SINGLE_SEL)

        #create GUI
        hidList.InsertColumn(0, self.text.deviceName)
        hidList.InsertColumn(1, self.text.manufacturer)
        hidList.InsertColumn(2, self.text.connected)

        path = GetDevicePath(
            devicePath,
            vendorID,
            productID,
            versionNumber,
            noOtherPort,
            useDeviceIndex,
            deviceIndex,
            deviceList)

        #fill list
        devices = {}
        idx = 0
        for item in deviceList:
            # eg.Print("VID=%X, PID=%X, name=%s" %(item.vendorId, item.productId, item.productString))
            # filter device list - list only match VID:PID
            if(
                ( ( item.vendorId == 0x054C or item.vendorId == 0x609 ) and item.productId == 0x0306 ) or
                item.devicePath == path or
                item.productString == 'BD Remote Control'
            ):
                idx = hidList.InsertStringItem(sys.maxint, item.productString)
                hidList.SetStringItem(idx, 1, item.vendorString)
                hidList.SetStringItem(idx, 2, self.text.yes)
                if item.devicePath == path:
                    hidList.Select(idx)
                devices[idx] = item

        #add not connected device to bottom of list
        if not path and devicePath:
            item = DeviceDescription(
                devicePath,
                vendorID,
                vendorString,
                productID,
                productString,
                versionNumber)
            idx = hidList.InsertStringItem(sys.maxint, item.productString)
            hidList.SetStringItem(idx, 1, item.vendorString)
            hidList.SetStringItem(idx, 2, self.text.no)
            hidList.Select(idx)
            devices[idx] = item

        #no device selected, disable ok and apply button
        panel.EnableButtons(hidList.GetFirstSelected() != -1)

        #layout
        for i in range(hidList.GetColumnCount()):
            hidList.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER)
            size = hidList.GetColumnWidth(i)
            hidList.SetColumnWidth(i, wx.LIST_AUTOSIZE)
            hidList.SetColumnWidth(i, max(size, hidList.GetColumnWidth(i) + 5))

        panel.sizer.Add(hidList, 1, flag = wx.EXPAND)

        #sizers
        optionsSizer = wx.GridBagSizer(0, 5)

        #eventname
        optionsSizer.Add(
            wx.StaticText(panel, -1, self.text.eventName),
            (0, 0),
            flag = wx.ALIGN_CENTER_VERTICAL)
        eventNameCtrl = wx.TextCtrl(panel, value = eventName)
        eventNameCtrl.SetMaxLength(32)
        optionsSizer.Add(eventNameCtrl, (0, 1), (1, 2), flag = wx.EXPAND)

        #checkbox for enduring event option
        enduringEventsCtrl = wx.CheckBox(panel, -1, self.text.enduringEvents)
        enduringEventsCtrl.SetValue(enduringEvents)
        optionsSizer.Add(enduringEventsCtrl, (1, 0), (1, 3))

        #text
        optionsSizer.Add(
            wx.StaticText(panel, -1, self.text.multipleDeviceOptions),
            (3, 0), (1, 3),
            flag = wx.ALIGN_CENTER_VERTICAL)

        #checkbox for use first device
        useDeviceIndexCtrl = wx.CheckBox(panel, -1, self.text.useDeviceIndex)
        useDeviceIndexCtrl.SetValue(useDeviceIndex)
        optionsSizer.Add(useDeviceIndexCtrl, (4, 0), (1, 2), flag = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)

        #device index spin control
        deviceIndexCtrl = eg.SpinIntCtrl(panel, -1, deviceIndex, 0, 99, size=(100,-1))
        optionsSizer.Add(deviceIndexCtrl, (4, 2), (1, 1))

        #checkbox for no other port option
        noOtherPortCtrl = wx.CheckBox(panel, -1, self.text.noOtherPort)
        noOtherPortCtrl.SetValue(noOtherPort)
        optionsSizer.Add(noOtherPortCtrl, (5, 0), (1, 3))

        panel.sizer.Add(optionsSizer, 0, wx.TOP, 10)

        def OnHidListSelect(event):
            panel.EnableButtons(hidList.GetFirstSelected() != -1)
            event.Skip()

        def OnUseDeviceIndexCtrlChange(event):
            noOtherPortCtrl.Enable(not useDeviceIndexCtrl.GetValue())
            deviceIndexCtrl.Enable(useDeviceIndexCtrl.GetValue())
            event.Skip()

        def OnNoOtherPortChange(event):
            useDeviceIndexCtrl.Enable(not noOtherPortCtrl.GetValue())
            deviceIndexCtrl.Enable(not noOtherPortCtrl.GetValue())
            event.Skip()

        OnUseDeviceIndexCtrlChange(wx.CommandEvent())
        OnNoOtherPortChange(wx.CommandEvent())
        useDeviceIndexCtrl.Bind(wx.EVT_CHECKBOX, OnUseDeviceIndexCtrlChange)
        noOtherPortCtrl.Bind(wx.EVT_CHECKBOX, OnNoOtherPortChange)
        hidList.Bind(wx.EVT_LIST_ITEM_SELECTED, OnHidListSelect)
        hidList.Bind(wx.EVT_LIST_ITEM_DESELECTED, OnHidListSelect)

        ######################################################################

        panel.sizer.Add((15,15))

        #sizers
        ps3GroupSizer = wx.StaticBoxSizer(
            wx.StaticBox(panel, -1, self.text.ps3Settings),
            wx.VERTICAL
        )

        ps3Sizer = wx.GridBagSizer(0, 5)

        #checkbox for ps3 release event
        ps3ReleaseCtrl = wx.CheckBox(panel, -1, self.text.ps3Release)
        ps3ReleaseCtrl.SetValue(ps3Release)
        ps3Sizer.Add(ps3ReleaseCtrl, (0, 0), (1, 3))

        #sleep time
        ps3Sizer.Add(
            wx.StaticText(panel, -1, self.text.sleepTime),
            (2, 0), flag = wx.ALIGN_CENTER_VERTICAL)
        sleepTimeCtrl = eg.SpinNumCtrl(
            panel, -1, sleepTime, size=(200,-1), integerWidth=7, increment=1.00
        )
        ps3Sizer.Add(sleepTimeCtrl, (2, 1), flag = wx.EXPAND)
        ps3Sizer.Add(
            wx.StaticText(panel, -1, self.text.seconds),
            (2, 2), (1, 2),
            flag = wx.ALIGN_CENTER_VERTICAL)

        #hibernate time
        ps3Sizer.Add(
            wx.StaticText(panel, -1, self.text.hibernateTime),
            (3, 0), flag = wx.ALIGN_CENTER_VERTICAL)
        hibernateTimeCtrl = eg.SpinNumCtrl(
            panel, -1, hibernateTime, size=(200,-1), integerWidth=7, increment=1.00
        )
        ps3Sizer.Add(hibernateTimeCtrl, (3, 1), flag = wx.EXPAND)
        ps3Sizer.Add(
            wx.StaticText(panel, -1, self.text.seconds),
            (3, 2), (1, 2),
            flag = wx.ALIGN_CENTER_VERTICAL)

        ps3GroupSizer.Add(ps3Sizer, 0, wx.ALL, 10)
        panel.sizer.Add(ps3GroupSizer, 0, wx.EXPAND)

        def OnEnduringEventsChange(event):
            ps3ReleaseCtrl.Enable( not enduringEventsCtrl.GetValue() )
            event.Skip()

        OnEnduringEventsChange(wx.CommandEvent())

        enduringEventsCtrl.Bind(wx.EVT_CHECKBOX, OnEnduringEventsChange)

        ######################################################################

        while panel.Affirmed():
            device = devices[hidList.GetFirstSelected()]
            panel.SetResult(
                eventNameCtrl.GetValue(),
                enduringEventsCtrl.GetValue(),
                False,
                True,
                ps3ReleaseCtrl.GetValue(),
                False,
                0.0,
                0.0,
                sleepTimeCtrl.GetValue(),
                hibernateTimeCtrl.GetValue(),
                noOtherPortCtrl.GetValue(),
                device.devicePath,
                device.vendorId,
                device.vendorString,
                device.productId,
                device.productString,
                device.versionNumber,
                useDeviceIndexCtrl.GetValue(),
            )
Example #3
0
class FS20PCE(eg.PluginClass):
    def __init__(self):
        self.version = None
        self.thread = None
        self.PendingEvents = {}
        self.mappings = None

    def RawCallback(self, data):
        if not data or len(data) != 13 or ord(data[0]) != 2 or ord(
                data[1]) != 11:
            self.PrintError("invalid data")
            return

        self.version = ord(data[12])

        houseCode = binascii.hexlify(data[2:6])
        deviceCode = binascii.hexlify(data[6:8])
        command = ord(data[8])
        names = self.GetGroupNames(houseCode, deviceCode)

        #cancel pending events
        for deviceName in names:
            if deviceName in self.PendingEvents:
                #cancel pending events for this device
                try:
                    timerEntry = self.PendingEvents[deviceName]
                    startTime, func, args, kwargs = timerEntry
                    eg.scheduler.CancelTask(timerEntry)
                    self.TriggerEvent(deviceName + ".Cancel", payload=args[1])
                    del self.PendingEvents[deviceName]
                except KeyError:
                    #may happen due to multithreaded access to self.PendingEvents dict
                    pass
                except ValueError:
                    #may happen due to multithreaded access to eg.scheduler's internal list
                    pass

            validTime = ord(data[9]) > 15
            if validTime:
                timeStr = binascii.hexlify(data[9:12])
                timeStr = timeStr[1:]  #cut the one
                eventTime = float(timeStr) * 0.25
            else:
                eventTime = 0

            if command in DirectCommands:
                commandStr0 = DirectCommands[command]
                commandStr1 = None
                payload0 = (eventTime)
            elif command in DelayedCommands:
                if (validTime and eventTime):
                    commandStr0 = None
                    commandStr1 = DelayedCommands[command]
                    payload0 = (eventTime, commandStr1)
                else:
                    commandStr0 = DelayedCommands[command]
                    commandStr1 = None
                    payload0 = None
            elif command in DoubleCommands:
                commandStr0, commandStr1 = DoubleCommands[command]
                payload0 = (eventTime, commandStr1)
            else:
                commandStr0 = binascii.hexlify(data[8]).upper()
                commandStr1 = None
                payload0 = None

            if (commandStr0):
                self.TriggerEvent(deviceName + "." + commandStr0,
                                  payload=payload0)
            else:
                self.TriggerEvent(deviceName + ".Timer", payload=payload0)

            if (commandStr1):
                if (eventTime > 0):
                    timerEntry = eg.scheduler.AddShortTask(
                        eventTime, self.SchedulerCallback, deviceName,
                        commandStr1)
                    self.PendingEvents[deviceName] = timerEntry
                else:
                    self.TriggerEvent(deviceName + "." + commandStr1)

    def SchedulerCallback(self, deviceName, commandStr):
        if deviceName in self.PendingEvents:
            #cancel pending events for this device
            try:
                timerEntry = self.PendingEvents[deviceName]
                startTime, func, args, kwargs = timerEntry
                if (args[1] == commandStr):
                    #maybe an old entry if commandStr does not match
                    self.TriggerEvent(deviceName + "." + commandStr)
                    del self.PendingEvents[deviceName]
            except KeyError:
                #may happen due to multithreaded access to self.PendingEvents dict
                pass

    def GetGroupNames(self, houseCode, deviceCode):
        names = [houseCode + "." + deviceCode]
        if self.mappings:
            for houseCodePattern, deviceCodePattern, deviceName in self.mappings:
                if (deviceName in names):
                    continue
                if CheckPattern(deviceCodePattern,
                                deviceCode) and CheckPattern(
                                    houseCodePattern, houseCode):
                    names.append(deviceName)
        return names

    def PrintVersion(self):
        #create the following python command to show version number
        #eg.plugins.FS20PCE.plugin.PrintVersion()
        if self.version == None:
            print "Need to receive data first. Please press a button and try again."
        else:
            versionMajor = self.version / 16
            versionMinor = self.version % 16
            print "Firmware version %d.%d" % (versionMajor, versionMinor)

    def StopCallback(self):
        self.TriggerEvent("Stopped")
        self.thread = None

    def GetMyDevicePath(self):
        path = GetDevicePath(None, VENDOR_ID, PRODUCT_ID, None, 0, True, 0)
        return path

    def SetupHidThread(self, newDevicePath):
        #create thread
        self.thread = HIDThread(self.name, newDevicePath, self.name)
        self.thread.start()
        self.thread.SetStopCallback(self.StopCallback)
        self.thread.SetRawCallback(self.RawCallback)

    def ReconnectDevice(self, event):
        """method to reconnect a disconnect device"""
        if self.thread == None:
            if not IsDeviceName(event.payload, VENDOR_ID, PRODUCT_ID):
                return

            #check if the right device was connected
            #getting devicePath
            newDevicePath = self.GetMyDevicePath()
            if not newDevicePath:
                #wrong device
                return

            self.SetupHidThread(newDevicePath)

    def __start__(self, mappings=None):
        self.mappings = mappings

        #Bind plug in to RegisterDeviceNotification message
        eg.Bind("System.DeviceAttached", self.ReconnectDevice)

        newDevicePath = self.GetMyDevicePath()
        if not newDevicePath:
            #device not found
            self.PrintError(Text.errorFind)
        else:
            self.SetupHidThread(newDevicePath)

    def __stop__(self):
        if self.thread:
            self.thread.AbortThread()

        #unbind from RegisterDeviceNotification message
        eg.Unbind("System.DeviceAttached", self.ReconnectDevice)

    def Configure(
        self,
        mappings=None,
    ):
        #gui callbacks and helper methods
        def ValidChars(input):
            for char in input:
                if char != '1' and char != '2' and char != '3' and char != '4' and char != '?':
                    return False
            return True

        def ContainsItem(houseCode, deviceAddress, groupName):
            for i in range(0, mappingsList.GetItemCount()):
                if houseCode != mappingsList.GetItem(i, 0).GetText():
                    continue
                if deviceAddress != mappingsList.GetItem(i, 1).GetText():
                    continue
                if groupName != mappingsList.GetItem(i, 2).GetText():
                    continue
                return True
            return False

        def OnItemSelected(event):
            idx = mappingsList.GetFirstSelected()
            houseCodeTextCtrl.SetValue(mappingsList.GetItem(idx, 0).GetText())
            deviceAddressTextCtrl.SetValue(
                mappingsList.GetItem(idx, 1).GetText())
            groupNameCtrl.SetValue(mappingsList.GetItem(idx, 2).GetText())

        def EnableButtons(event):
            idx = mappingsList.GetFirstSelected()
            houseCode = houseCodeTextCtrl.GetValue()
            deviceAddress = deviceAddressTextCtrl.GetValue()
            groupName = groupNameCtrl.GetValue()
            valid = houseCodeTextCtrl.IsValid(
            ) and deviceAddressTextCtrl.IsValid() and len(groupName)

            itemSelected = idx != -1
            addButton.Enable(
                valid
                and not ContainsItem(houseCode, deviceAddress, groupName))
            updateButton.Enable(valid and itemSelected and \
                (houseCode != mappingsList.GetItem(idx, 0).GetText() \
                 or deviceAddress != mappingsList.GetItem(idx, 1).GetText() \
                 or groupName != mappingsList.GetItem(idx, 2).GetText()) \
                and not ContainsItem(houseCode, deviceAddress, groupName))
            deleteButton.Enable(itemSelected)
            event.Skip()

        def OnAddButton(event):
            idx = mappingsList.InsertStringItem(sys.maxint,
                                                houseCodeTextCtrl.GetValue())
            mappingsList.SetStringItem(idx, 1,
                                       deviceAddressTextCtrl.GetValue())
            mappingsList.SetStringItem(idx, 2, groupNameCtrl.GetValue())
            mappingsList.Select(idx)
            EnableButtons(event)
            event.Skip()

        def OnUpdateButton(event):
            idx = mappingsList.GetFirstSelected()
            mappingsList.SetStringItem(idx, 0, houseCodeTextCtrl.GetValue())
            mappingsList.SetStringItem(idx, 1,
                                       deviceAddressTextCtrl.GetValue())
            mappingsList.SetStringItem(idx, 2, groupNameCtrl.GetValue())
            EnableButtons(event)
            event.Skip()

        def OnDeleteButton(event):
            idx = mappingsList.GetFirstSelected()
            mappingsList.DeleteItem(idx)
            EnableButtons(event)
            event.Skip()

        panel = eg.ConfigPanel(self, resizable=True)

        #building dialog
        mappingsList = wx.ListCtrl(panel,
                                   -1,
                                   pos=wx.DefaultPosition,
                                   size=wx.DefaultSize,
                                   style=wx.LC_REPORT | wx.LC_SINGLE_SEL)

        #create list
        mappingsList.InsertColumn(0, Text.houseCode)
        mappingsList.InsertColumn(1, Text.deviceAddress)
        mappingsList.InsertColumn(2, Text.groupName)

        #add items
        if mappings:
            for item in mappings:
                idx = mappingsList.InsertStringItem(sys.maxint, item[0])
                mappingsList.SetStringItem(idx, 1, item[1])
                mappingsList.SetStringItem(idx, 2, item[2])

        #layout
        for i in range(mappingsList.GetColumnCount()):
            mappingsList.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER)
            size = mappingsList.GetColumnWidth(i)
            mappingsList.SetColumnWidth(i, wx.LIST_AUTOSIZE)
            mappingsList.SetColumnWidth(
                i, max(size,
                       mappingsList.GetColumnWidth(i) + 5))

        houseCodeTextCtrl = TextCtrl(
            panel,
            mask="XXXXXXXX",
            choiceRequired=True,
            validFunc=ValidChars,
            defaultValue="????????",
            formatcodes="F",
        )

        deviceAddressTextCtrl = TextCtrl(
            panel,
            mask="XXXX",
            choiceRequired=True,
            validFunc=ValidChars,
            defaultValue="????",
            formatcodes="F",
        )

        groupNameCtrl = wx.TextCtrl(panel)

        editSizer = wx.GridSizer(3, 2)
        editSizer.Add(wx.StaticText(panel, -1, Text.houseCode + ":"),
                      wx.ALIGN_CENTER_VERTICAL)
        editSizer.Add(houseCodeTextCtrl, 0)
        editSizer.Add(wx.StaticText(panel, -1, Text.deviceAddress + ":"),
                      wx.ALIGN_CENTER_VERTICAL)
        editSizer.Add(deviceAddressTextCtrl, 0)
        editSizer.Add(wx.StaticText(panel, -1, Text.groupName + ":"),
                      wx.ALIGN_CENTER_VERTICAL)
        editSizer.Add(groupNameCtrl, 0)

        addButton = wx.Button(panel, -1, Text.add)
        updateButton = wx.Button(panel, -1, Text.update)
        deleteButton = wx.Button(panel, -1, Text.delete)

        buttonsSizer = wx.GridSizer(1, 3)
        buttonsSizer.Add(addButton)
        buttonsSizer.Add(deleteButton)
        buttonsSizer.Add(updateButton)

        houseCodeTextCtrl.Bind(wx.EVT_TEXT, EnableButtons)
        deviceAddressTextCtrl.Bind(wx.EVT_TEXT, EnableButtons)
        groupNameCtrl.Bind(wx.EVT_TEXT, EnableButtons)

        addButton.Bind(wx.EVT_BUTTON, OnAddButton)
        updateButton.Bind(wx.EVT_BUTTON, OnUpdateButton)
        deleteButton.Bind(wx.EVT_BUTTON, OnDeleteButton)

        mappingsList.Bind(wx.EVT_LIST_ITEM_SELECTED, OnItemSelected)
        mappingsList.Bind(wx.EVT_LIST_ITEM_SELECTED, EnableButtons)
        mappingsList.Bind(wx.EVT_LIST_ITEM_DESELECTED, EnableButtons)
        EnableButtons(wx.CommandEvent())

        panel.sizer.Add(wx.StaticText(panel, -1, Text.help0))
        panel.sizer.Add(wx.StaticText(panel, -1, Text.help1))
        panel.sizer.Add(mappingsList, 1, flag=wx.EXPAND)
        panel.sizer.Add(editSizer)
        panel.sizer.Add(buttonsSizer)

        while panel.Affirmed():
            newMappings = []
            for i in range(0, mappingsList.GetItemCount()):
                item = mappingsList.GetItem(i, 0).GetText(), \
                    mappingsList.GetItem(i, 1).GetText(), \
                    mappingsList.GetItem(i, 2).GetText()
                newMappings.append(item)
            panel.SetResult(newMappings)
class HID(eg.PluginClass):
    def __init__(self):
        self.thread = None

    def RawCallback(self, data):
        self.TriggerEvent(binascii.hexlify(data).upper())

    def ButtonCallback(self, data):
        if len(data):
            #one or more buttons pressed
            btnPressed = []
            for num in data:
                btnPressed.append(str(num))
            evtName = "Button." + "+".join(btnPressed)
            if self.enduringEvents:
                self.TriggerEnduringEvent(evtName)
            else:
                self.TriggerEvent(evtName)
        elif self.enduringEvents:
            #no buttons pressed anymore
            self.EndLastEvent()
        else:
            #trigger event so that releasing all buttons
            #can get noticed even w/o enduring events
            self.TriggerEvent("Button.None")

    def ValueCallback(self, data):
        for key, value in data.items():
            if key in self.oldValues and value == self.oldValues[key]:
                continue
            self.oldValues[key] = value
            self.TriggerEvent("Value." + str(key), payload=value)

    def StopCallback(self):
        self.TriggerEvent("Stopped")
        self.thread = None

    def GetMyDevicePath(self):
        path = GetDevicePath(self.devicePath, self.vendorID, self.productID,
                             self.versionNumber, self.useDeviceIndex,
                             self.deviceIndex, self.noOtherPort)
        return path

    def SetupHidThread(self, newDevicePath):
        #create thread
        self.thread = HIDThread(self.vendorString + " " + self.productString,
                                newDevicePath)
        self.thread.start()
        self.thread.SetStopCallback(self.StopCallback)
        if self.rawDataEvents:
            self.thread.SetRawCallback(self.RawCallback)
        else:
            self.thread.SetButtonCallback(self.ButtonCallback)
            self.thread.SetValueCallback(self.ValueCallback)

    def ReconnectDevice(self, event):
        """method to reconnect a disconnect device"""
        if self.thread == None:
            if not IsDeviceName(event.payload, self.vendorID, self.productID):
                return

            #check if the right device was connected
            #getting devicePath
            newDevicePath = self.GetMyDevicePath()
            if not newDevicePath:
                #wrong device
                return

            self.SetupHidThread(newDevicePath)

    def GetLabel(self,
                 eventName,
                 enduringEvents,
                 rawDataEvents,
                 noOtherPort,
                 devicePath,
                 vendorID,
                 vendorString,
                 productID,
                 productString,
                 versionNumber,
                 useDeviceIndex=False,
                 deviceIndex=0):
        prefix = "HID: "
        #one or both strings empty should not happen
        if not vendorString or not productString:
            return "HID"

        #productString already contains manufacturer or vendor id only
        if productString.find(vendorString) != -1 or\
            vendorString[0:len(Text.vendorID)] == Text.vendorID:
            return prefix + productString

        return prefix + vendorString + " " + productString

    def __start__(self,
                  eventName,
                  enduringEvents,
                  rawDataEvents,
                  noOtherPort,
                  devicePath,
                  vendorID,
                  vendorString,
                  productID,
                  productString,
                  versionNumber,
                  useDeviceIndex=False,
                  deviceIndex=0):
        #saving parameters so they can be used to reconnect a device
        self.eventName = eventName
        self.enduringEvents = enduringEvents
        self.rawDataEvents = rawDataEvents
        self.noOtherPort = noOtherPort
        self.devicePath = devicePath
        self.vendorID = vendorID
        self.vendorString = vendorString
        self.productID = productID
        self.productString = productString
        self.versionNumber = versionNumber
        self.useDeviceIndex = useDeviceIndex
        self.deviceIndex = deviceIndex
        self.oldValues = {}

        if eventName:
            self.info.eventPrefix = eventName
        else:
            self.info.eventPrefix = "HID"

        #Bind plug in to RegisterDeviceNotification message
        eg.Bind("System.DeviceAttached", self.ReconnectDevice)

        newDevicePath = self.GetMyDevicePath()
        if not newDevicePath:
            #device not found
            self.PrintError(Text.errorFind)
        else:
            self.SetupHidThread(newDevicePath)

    def __stop__(self):
        if self.thread:
            self.thread.AbortThread()

        #unbind from RegisterDeviceNotification message
        eg.Unbind("System.DeviceAttached", self.ReconnectDevice)

    def Configure(self,
                  eventName="",
                  enduringEvents=True,
                  rawDataEvents=False,
                  noOtherPort=False,
                  devicePath=None,
                  vendorID=None,
                  vendorString=None,
                  productID=None,
                  productString=None,
                  versionNumber=None,
                  useDeviceIndex=False,
                  deviceIndex=0):
        deviceList = GetDeviceDescriptions()
        panel = eg.ConfigPanel(self, resizable=True)

        #building dialog
        hidList = wx.ListCtrl(panel,
                              -1,
                              pos=wx.DefaultPosition,
                              size=wx.DefaultSize,
                              style=wx.LC_REPORT | wx.LC_SINGLE_SEL)

        #create GUI
        hidList.InsertColumn(0, Text.deviceName)
        hidList.InsertColumn(1, Text.manufacturer)
        hidList.InsertColumn(2, Text.connected)

        path = GetDevicePath(devicePath, vendorID, productID, versionNumber,
                             noOtherPort, useDeviceIndex, deviceIndex,
                             deviceList)

        #fill list
        devices = {}
        idx = 0
        for item in deviceList:
            idx = hidList.InsertStringItem(sys.maxint, item.productString)
            hidList.SetStringItem(idx, 1, item.vendorString)
            hidList.SetStringItem(idx, 2, Text.yes)
            if item.devicePath == path:
                hidList.Select(idx)
            devices[idx] = item

        #add not connected device to bottom of list
        if not path and devicePath:
            item = DeviceDescription(devicePath, vendorID, vendorString,
                                     productID, productString, versionNumber)
            idx = hidList.InsertStringItem(sys.maxint, item.productString)
            hidList.SetStringItem(idx, 1, item.vendorString)
            hidList.SetStringItem(idx, 2, Text.no)
            hidList.Select(idx)
            devices[idx] = item

        #no device selected, disable ok and apply button
        panel.EnableButtons(hidList.GetFirstSelected() != -1)

        #layout
        for i in range(hidList.GetColumnCount()):
            hidList.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER)
            size = hidList.GetColumnWidth(i)
            hidList.SetColumnWidth(i, wx.LIST_AUTOSIZE)
            hidList.SetColumnWidth(i, max(size, hidList.GetColumnWidth(i) + 5))

        panel.sizer.Add(hidList, 1, flag=wx.EXPAND)

        #sizers
        optionsSizer = wx.GridBagSizer(0, 5)

        #eventname
        optionsSizer.Add(wx.StaticText(panel, -1, Text.eventName), (0, 0),
                         flag=wx.ALIGN_CENTER_VERTICAL)
        eventNameCtrl = wx.TextCtrl(panel, value=eventName)
        eventNameCtrl.SetMaxLength(32)
        optionsSizer.Add(eventNameCtrl, (0, 1), (1, 2), flag=wx.EXPAND)

        #checkbox for enduring event option
        enduringEventsCtrl = wx.CheckBox(panel, -1, Text.enduringEvents)
        enduringEventsCtrl.SetValue(enduringEvents)
        optionsSizer.Add(enduringEventsCtrl, (1, 0), (1, 3))

        #checkbox for raw data events
        rawDataEventsCtrl = wx.CheckBox(panel, -1, Text.rawDataEvents)
        rawDataEventsCtrl.SetValue(rawDataEvents)
        optionsSizer.Add(rawDataEventsCtrl, (2, 0), (1, 3))

        #text
        optionsSizer.Add(wx.StaticText(panel, -1, Text.multipleDeviceOptions),
                         (3, 0), (1, 3),
                         flag=wx.ALIGN_CENTER_VERTICAL)

        #checkbox for use first device
        useDeviceIndexCtrl = wx.CheckBox(panel, -1, Text.useDeviceIndex)
        useDeviceIndexCtrl.SetValue(useDeviceIndex)
        optionsSizer.Add(useDeviceIndexCtrl, (4, 0), (1, 2),
                         flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)

        #device index spin control
        deviceIndexCtrl = eg.SpinIntCtrl(panel,
                                         -1,
                                         deviceIndex,
                                         0,
                                         99,
                                         size=(100, -1))
        optionsSizer.Add(deviceIndexCtrl, (4, 2), (1, 1))

        #checkbox for no other port option
        noOtherPortCtrl = wx.CheckBox(panel, -1, Text.noOtherPort)
        noOtherPortCtrl.SetValue(noOtherPort)
        optionsSizer.Add(noOtherPortCtrl, (5, 0), (1, 3))

        panel.sizer.Add(optionsSizer, 0, wx.TOP, 10)

        def OnHidListSelect(event):
            panel.EnableButtons(hidList.GetFirstSelected() != -1)
            event.Skip()

        def OnRawDataEventsChange(event):
            enduringEventsCtrl.Enable(not rawDataEventsCtrl.GetValue())
            event.Skip()

        def OnEnduringEventsChange(event):
            rawDataEventsCtrl.Enable(not enduringEventsCtrl.GetValue())
            event.Skip()

        def OnUseDeviceIndexCtrlChange(event):
            noOtherPortCtrl.Enable(not useDeviceIndexCtrl.GetValue())
            deviceIndexCtrl.Enable(useDeviceIndexCtrl.GetValue())
            event.Skip()

        def OnNoOtherPortChange(event):
            useDeviceIndexCtrl.Enable(not noOtherPortCtrl.GetValue())
            deviceIndexCtrl.Enable(not noOtherPortCtrl.GetValue())
            event.Skip()

        OnRawDataEventsChange(wx.CommandEvent())
        OnEnduringEventsChange(wx.CommandEvent())
        OnUseDeviceIndexCtrlChange(wx.CommandEvent())
        OnNoOtherPortChange(wx.CommandEvent())
        rawDataEventsCtrl.Bind(wx.EVT_CHECKBOX, OnRawDataEventsChange)
        enduringEventsCtrl.Bind(wx.EVT_CHECKBOX, OnEnduringEventsChange)
        useDeviceIndexCtrl.Bind(wx.EVT_CHECKBOX, OnUseDeviceIndexCtrlChange)
        noOtherPortCtrl.Bind(wx.EVT_CHECKBOX, OnNoOtherPortChange)
        hidList.Bind(wx.EVT_LIST_ITEM_SELECTED, OnHidListSelect)
        hidList.Bind(wx.EVT_LIST_ITEM_DESELECTED, OnHidListSelect)

        while panel.Affirmed():
            device = devices[hidList.GetFirstSelected()]
            panel.SetResult(
                eventNameCtrl.GetValue(),
                enduringEventsCtrl.GetValue(),
                rawDataEventsCtrl.GetValue(),
                noOtherPortCtrl.GetValue(),
                device.devicePath,
                device.vendorId,
                device.vendorString,
                device.productId,
                device.productString,
                device.versionNumber,
                useDeviceIndexCtrl.GetValue(),
                deviceIndexCtrl.GetValue(),
            )
Example #5
0
class USB_RFID(eg.PluginClass):
    text = Text

    def __init__(self):
        self.version = None
        self.thread = None

        self.AddNewAction("GreenLED", 0xf2, "Green LED", "Turn on green LED",
                          "Turn on green LED for {0}0 ms")
        self.AddNewAction("RedLED", 0xf1, "Red LED", "Turn on red LED",
                          "Turn on red LED for {0}0 ms")
        self.AddNewAction("Buzzer", 0xf3, "Buzzer", "Turn on buzzer",
                          "Turn on buzzer for {0}0 ms")

    def AddNewAction(self, internalName, classFuncCode, externalName,
                     classDescription, classLabelFormat):
        class MyText:
            labelFormat = classLabelFormat

        class tmpAction(ActionBase):
            text = MyText
            name = externalName
            description = classDescription
            funcCode = classFuncCode

        tmpAction.__name__ = internalName
        self.AddAction(tmpAction)

    def RawCallback(self, data):
        if eg.debugLevel:
            print "USB_RFID RawCallBack", binascii.hexlify(data)

        if len(data) != 9 or data[0:3] != "\x02\x07\xA0":
            self.PrintError(
                "data must have a length of 9 and start with 02 07 A0")
        errorId = ord(data[3:4])
        if errorId == 0:
            pass
            #everything is fine
        elif errorId == 1:
            #Firmware version was requested
            self.version = ord(data[4:5])
        elif errorId == 2:
            #Firmware version was requested
            self.version = ord(data[4:5])
        elif errorId == 3:
            self.PrintError("invalid command length")
        elif errorId == 4 or errorId == 5:
            eventstring = binascii.hexlify(
                data[4:5]).upper() + "." + binascii.hexlify(data[5:]).upper()
            knownCode = False
            for eventHandler in eg.eventTable.get(
                    self.info.eventPrefix + "." + eventstring, []):
                knownCode = True
                break
            self.TriggerEvent(eventstring)
            if not knownCode:
                self.TriggerEvent("Unknown")

        else:
            self.PrintError("Unknown Error")

    def PrintVersion(self):
        #create the following python command to show version number
        #eg.plugins.USB-RFID.plugin.PrintVersion()
        versionMajor = self.version / 16
        versionMinor = self.version % 16
        print "Firmware version %d.%d" % (versionMajor, versionMinor)

    def StopCallback(self):
        self.TriggerEvent("Stopped")
        self.thread = None

    def GetMyDevicePath(self):
        path = GetDevicePath(None, VENDOR_ID, PRODUCT_ID, None, 0, True, 0)
        return path

    def SetupHidThread(self, newDevicePath):
        #create thread
        self.thread = HIDThread(self.name, newDevicePath, self.name)
        self.thread.SetStopCallback(self.StopCallback)
        self.thread.SetRawCallback(self.RawCallback)
        self.thread.start()
        self.thread.WaitForInit()
        self.RequestVersion()

    def RequestVersion(self):
        self.thread.Write('\x01\x01\xf0\x00\x00', 1000)

    def ReconnectDevice(self, event):
        """method to reconnect a disconnect device"""
        if self.thread == None:
            if not IsDeviceName(event.payload, VENDOR_ID, PRODUCT_ID):
                return

            #check if the right device was connected
            #getting devicePath
            newDevicePath = self.GetMyDevicePath()
            if not newDevicePath:
                #wrong device
                return

            self.SetupHidThread(newDevicePath)

    def __start__(self):
        #Bind plug in to RegisterDeviceNotification message
        eg.Bind("System.DeviceAttached", self.ReconnectDevice)

        newDevicePath = self.GetMyDevicePath()
        if not newDevicePath:
            #device not found
            self.PrintError(Text.errorFind)
        else:
            self.SetupHidThread(newDevicePath)

    def __stop__(self):
        if self.thread:
            self.thread.AbortThread()

        #unbind from RegisterDeviceNotification message
        eg.Unbind("System.DeviceAttached", self.ReconnectDevice)