I have this script for EZIO running. I modded it slightly so that it correctly updates status when the device triggers, but sometimes HS misses a status change. So I run the script with "EZIOPollDevices" to get a device status update. This works great 1 time. After that it always says "the script is already running waiting for it to end before running again." I do not know why this is. Also despite my config setting, this script never seems to time out.
Any help would be greatly appreciated.
Regards,
CodeMonkey
Any help would be greatly appreciated.
Regards,
CodeMonkey
Code:
' ' LAST UPDATE: 19 Oct 2007, Jeffry Dwight ' ' This script assumes you are using the EZIO2x4 as follows: ' ' 1. The EZIO2x4 is configured with the default settings, except that ' relays 1 and 2 each have timers set to 2, the timers are enabled, ' and the timers are set to mean seconds. Configure these settings ' using SimpleHomeNet's utility. ' ' 2. Relays 1 and 2 are wired in parallel with garge door opener ' switches, so that actuating a relay is the same as pushing the ' opener button (and the auto-off timer from assumption 1 therefore ' provides releasing the opener button). ' ' 3. Inputs 1 and 2 are being used with dry contacts to monitor the ' status of garage doors operated by relays 1 and 2. ' ' TO USE THIS SCRIPT: ' ' 1. Plug in your own EZIO2x4's Insteon address in g_szEZIO_Address ' below. ' ' 2. Place this script in your HomeSeer's scripts folder. ' ' 3. Add the this line: ' ' hs.RunEx("EZIO2x4-Garage.vb","RegisterDevices",parm) ' ' to your existing Insteon_ExtDevSupport.vb script's RegisterDevices ' routine (right after the Try is a good place). ' ' 4. You may use the HomeSeer devices this script creates in any of your ' HomeSeer scripts or events. ' ' 5. Your scripts/events may call EZIOPollDevices at any time to force a ' poll of inputs 1-4 and update status (not necessary if Insteon ' broadcasts are reliable in your home, but nice to have for times ' when things get out of sync). ' ' 6. Your scripts/events may call EZIOOperateRelay to switch on one of ' the relays (pass 1 or 2 as the parm to specify which relay). Const Private g_szScriptName As String = "EZIO2x4-Garage.vb" Const Private g_szEZIO_Address As String = "01.70.82" ' The Insteon address of the EZIO controller Const Private g_szEZIO_DevName As String = "EZIO1" ' A unique name for the EZIO device. Const Private g_szEZIO_DevLocation As String = "Garage" ' The location for the EZIO HomeSeer device info Const Private g_szEZIO_HouseCode As String = "G" ' We are going to use this House Code Const Private g_dwEZIO_FirstDeviceCode As Integer = 1 ' The Device Code (DC) that will hold the first EZIO device Const Private g_bEZIO_Enabled As Boolean = True ' Set to True to enable EZIO2x4 support, False to disable Dim Private g_bEZIO_Busy As Boolean = False ' We need to know if EZIO device change messages are caused by our own functions Dim Private g_bDebug As Boolean = 0 ' Enable for lots of nice logging in HomeSeer's log ' ' ----- Call this method from the RegisterDevices() of Insteon_ExtDevSupport.vb ' Public Sub RegisterDevices(ByVal parm As Object) Try g_bEZIO_Busy = False If g_bEZIO_Enabled Then hs.plugin("Insteon").ExtDev_RegisterExternalDeviceSupport(g_szEZIO_DevName,g_szEZIO_Address,g_szScriptName,"EZIOReceiveData") EZIOCreateDevices() hs.plugin("Insteon").ExtDev_TransmitToExternalDevice(g_szEZIO_DevName,&H7,&H46,0) ' turn off relay one hs.plugin("Insteon").ExtDev_TransmitToExternalDevice(g_szEZIO_DevName,&H7,&H46,1) ' turn off relay two EZIOPollDevices(vbNull) ' refresh with actual values reported by device EZIOProcessStatus(&hF0) ' we just set the relays off, so assume openers NOT operating End If hs.RegisterStatusChangeCB(g_szScriptName,"EZIOStatusChangeCallback") Catch ex As Exception hs.WriteLog(g_szScriptName, "Error in RegisterDevices " & ex.ToString) End Try End Sub ' ' ----- The Insteon plug-in calls this routine every time a device changes ' Public Sub EZIOStatusChangeCallback(ByVal parms) Dim hc As String Dim dc As Integer Dim Status As Integer Try If g_bEZIO_Enabled Then hc = parms(0) dc = parms(1) Status = parms(2) If (hc = g_szEZIO_HouseCode) AND (dc >= g_dwEZIO_FirstDeviceCode) AND (dc <= g_dwEZIO_FirstDeviceCode + 1) AND (g_bEZIO_Busy = False) Then If Status = 2 Then ' Turn On hs.plugin("Insteon").ExtDev_TransmitToExternalDevice(g_szEZIO_DevName,&H7,&H45,(dc - g_dwEZIO_FirstDeviceCode)) ElseIf Status = 3 Then ' Turn Off hs.plugin("Insteon").ExtDev_TransmitToExternalDevice(g_szEZIO_DevName,&H7,&H46,(dc - g_dwEZIO_FirstDeviceCode)) End If End If End If ' end if g_bEZIO_Enabled Catch ex As Exception hs.WriteLog(g_szScriptName,"Error in StatusChangeCallback:" & ex.ToString) End Try End Sub ' ' ----- Operate EZIO relay x (may be called from external scripts or from within HomeSeer) ' Public Sub EZIOOperateRelay(parms as object) Dim iDevice as Integer Try If g_bEZIO_Enabled Then iDevice = parms If iDevice >= 1 AND iDevice <= 2 Then hs.plugin("Insteon").ExtDev_TransmitToExternalDevice(g_szEZIO_DevName,&H7,&H45,iDevice - 1) if g_bDebug Then hs.WriteLog(g_szScriptname,"EZIOOperateRelay: Sending 0x45 for unit " & iDevice) Else hs.WriteLog(g_szScriptname,"EZIOOperateRelay: Was expecting 1 or 2 as parameter") End If End If Catch ex As Exception hs.WriteLog(g_szScriptName,"Error in EZIOOperateRelay: " & ex.ToString) End Try End Sub ' ' ----- Poll EZIO (may be called from external scripts or from within HomeSeer) ' Public Sub EZIOPollDevices(parms as object) Try If g_bEZIO_Enabled Then hs.plugin("Insteon").ExtDev_TransmitToExternalDevice(g_szEZIO_DevName,&H7,&H49,0) if g_bDebug Then hs.WriteLog(g_szScriptname,"EZIOPollDevices: Sending 0x49 to request report") End If Catch ex As Exception hs.WriteLog(g_szScriptName,"Error in EZIOPollDevices: " & ex.ToString) End Try End Sub ' ' ----- The Insteon plug-in calls this routine every time there's data from our device ' Public Sub EZIOReceiveData(ByVal InsteonData As String) Dim Data() As String Dim Flags As Long Dim Status As Long Dim MsgType As Long Try If g_bDebug Then hs.WriteLog(g_szScriptName,"Received Insteon Data: " & InsteonData) Data = Split(InsteonData, " ") If Data(0) = "ACK" Then ' This was an ACK response to a prior command. There is extra data here. The standard ACK will also be sent Select Case Val("&h" & Data(1)) Case &H49 ' Ack was to a Sensor Report command if g_bDebug Then EZIOSensorReport(Val("&h" & Data(2)), Val("&h" & Data(12))) End Select Else ' This is a standard Insteon message Flags = CLng("&H" & Data(7)) If g_bDebug Then hs.WriteLog(g_szScriptName,"FlagsRaw=" & Hex$(Flags) & ", masked=" & Hex$(Flags AND &hE0)) Select Case (Flags AND &hE0) Case &h80 ' Broadcast transmissions from our device MsgType = CLng("&h" & Data(8)) ' 0x27 means input sensor status change Status = CLng("&h" & Data(9)) ' bit-mapped, 0=all off, 1=1 on, 2=2 on, 3=1 and 2 on, etc. If g_bDebug Then hs.WriteLog(g_szScriptName,"Got broadcast from our device: MsgType=" & Hex$(MsgType) & ", BitMap=" & Hex$(Status)) If MsgType = &H27 Then EZIOProcessStatus(Status) ' Input sensor change status report End If Case &h20 ' Ack replies from our device to any other device MsgType = CLng("&h" & Data(8)) Status = CLng("&h" & Data(9)) ' bit-mapped, 0=all off, 1=1 on, 2=2 on, 3=1 and 2 on, etc. If g_bDebug Then hs.WriteLog(g_szScriptName,"Got ACK from command to our device: MsgType=" & Hex$(MsgType) & ", BitMap=" & Hex$(Status)) If MsgType = &H49 Or MsgType = &h45 OR MsgType = &h46 Then EZIOProcessStatus(Status) ' Input sensor change status report End If Case &hC0 ' Group control broadcast commands from our device EZIOProcessBroadcast(Val("&h" & Data(5)), Val("&h" & Data(7))) Case &hA0 ' Nak replies from our device to any other device If g_bDebug Then hs.WriteLog(g_szScriptName,"NAK from our device to some other device") Case &h00 ' Direct commands from our device to any other device If g_bDebug Then hs.WriteLog(g_szScriptName,"Direct from our device to some other device") Case &h40 ' Group control clean-up commands from our device If g_bDebug Then hs.WriteLog(g_szScriptName,"Group Cleanup from our device") EZIOPollDevices(vbNull) ' refresh with actual values reported by device Case &h60 ' Ack replies from our device to group clean-up commands from any device If g_bDebug Then hs.WriteLog(g_szScriptName,"ACK to group cleanup") Case &hE0 ' Nak replies from our device to group clean-up commands from any device If g_bDebug Then hs.WriteLog(g_szScriptName,"NAK to group cleanup") End Select End If Catch ex As Exception hs.WriteLog(g_szScriptName,"Error in EzIOReceiveData: " & ex.ToString) End Try End Sub ' ' ------ Create input and output virtual devices (only if they don't already exist) ' Private Sub EZIOCreateDevices() Dim Lp As Integer Dim Ref As Long Dim dv As Object Dim dc As String Dim DevName As String Dim Button As String Dim Label As String if g_bDebug Then hs.WriteLog(g_szScriptName,"EZIOCreateDevices(): Starting") Try g_bEZIO_Busy = True For Lp = 0 To 5 dc = (g_dwEZIO_FirstDeviceCode + Lp).ToString If hs.DeviceExists(g_szEZIO_HouseCode & dc) = -1 Then Select Case Lp Case 0,1 DevName = "Garage Opener " & (Lp + 1).ToString Button = g_szScriptName & "(""EZIOOperateRelay"",""" & Lp + 1 & """)" Label = "Operate" Case Else DevName = "Garage Door " & (Lp - 2 + 1).ToString Button = g_szScriptName & "(""EZIOPollDevices"",""0"")" Label = " Verify " End Select Ref = hs.NewDeviceRef (DevName) dv = hs.GetDeviceByRef(Ref) dv.hc = g_szEZIO_HouseCode dv.dc = dc dv.can_dim = False dv.location = g_szEZIO_DevLocation dv.location2 = "auto-created" dv.misc = &h10 dv.dev_type_string = "Status Only" hs.SetDeviceValue (DevName,0) hs.SetDeviceString (DevName,"Unverified",False) hs.SetDeviceStatus (DevName,3) hs.SaveEventsDevices() hs.DeviceButtonAdd (g_szEZIO_HouseCode & dc,Button,Label) hs.WriteLog (g_szScriptName,"Created device " & DevName & " as " & g_szEZIO_HouseCode & dc) End If Next Catch ex As Exception hs.WriteLog(g_szScriptName,"Error in EZIOCreateDevices: " & ex.ToString) End Try g_bEZIO_Busy = False if g_bDebug Then hs.WriteLog(g_szScriptName,"EZIOCreateDevices(): Finished") End Sub ' ' ----- helper function: returns numeric code meaning "on" or "off" ' Private Function EZIOOnOffCode (ByVal Code as Byte) as Byte If Code Then EZIOOnOffCode = 2 ' on Else EZIOOnOffCode = 3 ' off End If End Function ' ' ----- helper function: returns string representing device status ' Private Function EZIODevStatus (ByVal Code as Byte,ByVal DC as Integer) as String Select Case DC ' NOTE: This is the DC, which is one more than the "real" device number! Case 1,2 ' relays Select Case Code Case 2: EZIODevStatus = "Moving" Case 3: EZIODevStatus = "Stopped" Case Else: EZIODevStatus = "Unknown" End Select Case Else ' garage door sensors and fence gate sensors Select Case Code Case 2: EZIODevStatus = "Closed" Case 3: EZIODevStatus = "Open" Case Else: EZIODevStatus = "Unknown" End Select End Select End Function Private Function EZIODevValue (ByVal Code as Byte) As Long If Code = 2 Then EZIODevValue = 1 ElseIf Code = 3 Then EZIODevValue = 0 'ElseIf Code = 4 Then ' EZIODevValue = 50 Else EZIODevValue = 999 End If End Function Private Function EZIODevString(ByVal Code as Byte,DC as Integer) As String Select Case DC ' NOTE: This is the DC, which is one more than the "real" device number! Case 1,2 ' relays Select Case Code Case 2: EZIODevString = "Moving" Case 3: EZIODevString = "Stopped" Case Else: EZIODevString = "Unknown" End Select Case 3 ' garage door sensors Select Case Code Case 2: EZIODevString = "<font color=GREEN><b>Door Closed</b></font> at " & Now Case 3: EZIODevString = "<font color=RED><b>Door Open</b></font> at " & Now Case Else: EZIODevString = "<font color=BLUE><b>Unknown Status</b></font> at " & Now End Select Case 4 ' Car Sensor Select Case Code Case 2: EZIODevString = "<font color=GREEN><b>Car in Garage</b></font> at " & Now Case 3: EZIODevString = "<font color=RED><b>Garage Empty</b></font> at " & Now Case Else: EZIODevString = "<font color=BLUE><b>Unknown Status</b></font> at " & Now End Select Case Else ' fence gate sensors Select Case Code Case 2: EZIODevString = "<font color=GREEN><b>Gate Closed</b></font> at " & Now Case 3: EZIODevString = "<font color=RED><b>Gate Open</b></font> at " & Now Case Else: EZIODevString = "<font color=BLUE><b>Unknown Status</b></font> at " & Now End Select End Select End Function ' ' ----- helper routine: changes virtual devices (only if new value differs from old value) ' Private Sub EZIOSetIfChanged(ByVal HC as String,ByVal DC as String,ByVal NewCode as Byte) Dim OldCode as Byte Dim OldStatus as String Dim NewStatus as String Dim NewValue as Long Dim NewString as String OldCode = hs.DeviceStatus(HC & DC) OldStatus = EZIODevStatus (OldCode,DC) If OldCode <> NewCode Then NewStatus = EZIODevStatus (NewCode,DC) NewValue = EZIODevValue (NewCode) NewString = EZIODevString (NewCode,DC) hs.WriteLog(g_szScriptName,"EZIO " & HC & DC & " changed from " & OldStatus & " to " & NewStatus) hs.SetDeviceStatus(HC & DC,NewCode) hs.SetDeviceString(HC & DC,NewString,False) hs.SetDeviceValue (HC & DC,NewValue) ElseIf g_bDebug Then hs.WriteLog(g_szScriptName,"EZIO " & HC & DC & " was already " & OldStatus & "; no change") End If End Sub ' ' ----- helper routine: processes EZIO device change status messages ' Private Sub EZIOProcessStatus(ByVal Status As Byte) If g_bDebug Then hs.WriteLog(g_szScriptName,"EZIOProcessStatus(): " & Hex$(Status)) Try g_bEZIO_Busy = True If (Status > 127) Then EZIOSetIfChanged(g_szEZIO_HouseCode,(g_dwEZIO_FirstDeviceCode + 0).ToString,EZIOOnOffCode(Status AND 1)) EZIOSetIfChanged(g_szEZIO_HouseCode,(g_dwEZIO_FirstDeviceCode + 1).ToString,EZIOOnOffCode(Status AND 2)) Else EZIOSetIfChanged(g_szEZIO_HouseCode,(g_dwEZIO_FirstDeviceCode + 2).ToString,EZIOOnOffCode(Status AND 1)) EZIOSetIfChanged(g_szEZIO_HouseCode,(g_dwEZIO_FirstDeviceCode + 3).ToString,EZIOOnOffCode(Status AND 2)) EZIOSetIfChanged(g_szEZIO_HouseCode,(g_dwEZIO_FirstDeviceCode + 4).ToString,EZIOOnOffCode(Status AND 4)) EZIOSetIfChanged(g_szEZIO_HouseCode,(g_dwEZIO_FirstDeviceCode + 5).ToString,EZIOOnOffCode(Status AND 8)) End If Catch ex As Exception hs.WriteLog(g_szScriptName,"Error in EZIOProcessStatus: " & ex.ToString) End Try g_bEZIO_Busy = False End Sub ' ' ----- helper routine: logs so-called "sensor reports" ' Private Sub EZIOSensorReport(ByVal Sensor As Byte, ByVal Value As Byte) Try hs.WriteLog(g_szScriptName,"EZIOSensorReport: Unit=" & Sensor.ToString & ", State=" & Value.ToString) Catch ex As Exception hs.WriteLog(g_szScriptName,"Error in EZIOSensorReport: " & ex.ToString) End Try End Sub ' ' ----- helper routine: processes EZIO device broadcasts ' Private Sub EZIOProcessBroadcast(ByVal GroupNum As Byte, ByVal CmdNum As Byte) Dim dc As String Try If g_bDebug Then hs.WriteLog(g_szScriptName,"EZIOProcessBroadcast: " & GroupNum.ToString & ", " & CmdNum.ToString) If GroupNum >= 1 AND GroupNum <= 4 Then ' makes SILLY assumption that sensor 1 is sending group 1, 2 sends 2, and so forth! dc = (g_dwEZIO_FirstDeviceCode + 2 + GroupNum).ToString Select Case CmdNum Case &H11: hs.SetDeviceStatus(g_szEZIO_HouseCode & dc, 2) ' Set to on Case &H13: hs.SetDeviceStatus(g_szEZIO_HouseCode & dc, 3) ' Set to off End Select End If Catch ex As Exception hs.WriteLog(g_szScriptName,"Error in EZIOProcessBroadcast: " & ex.ToString) End Try End Sub
Comment