The files contained in this repository can be downloaded to your computer using a svn client.
On Linux you simply type the command displayed below.
This URL has Read-Only access.
root / trunk / DomotiGa / CUPS.class @ 550
History | View | Annotate | Download (6.2 kB)
| 1 | 2 | riemers | ' Gambas class file |
|---|---|---|---|
| 2 | 2 | riemers | |
| 3 | 2 | riemers | ' Description: |
| 4 | 2 | riemers | ' CCUPS.class |
| 5 | 2 | riemers | ' Connect to UPS via upsd's tcp socket and monitor status. |
| 6 | 2 | riemers | |
| 7 | 2 | riemers | ' Development Status: |
| 8 | 2 | riemers | ' Working, maybe later add more variables to monitor. |
| 9 | 2 | riemers | ' Only tested with my APC SmartUPS 1000, only one UPS at a time supported. |
| 10 | 2 | riemers | |
| 11 | 2 | riemers | ' DomotiGa - an open source home automation program. |
| 12 | 526 | rdnzl | ' Copyright(C) 2008-2011 Ron Klinkien |
| 13 | 2 | riemers | |
| 14 | 25 | rdnzl | ' Read file called COPYING for license details. |
| 15 | 2 | riemers | |
| 16 | 2 | riemers | PROPERTY Host AS String |
| 17 | 2 | riemers | PROPERTY Port AS Integer |
| 18 | 2 | riemers | PROPERTY PollTime AS Integer |
| 19 | 2 | riemers | PROPERTY UPSDebug AS Boolean |
| 20 | 2 | riemers | |
| 21 | 245 | rdnzl | PRIVATE sTCPHost AS String |
| 22 | 245 | rdnzl | PRIVATE iTCPPort AS Integer |
| 23 | 2 | riemers | PRIVATE iPollTime AS Integer |
| 24 | 2 | riemers | PRIVATE bUPSDebug AS Boolean |
| 25 | 2 | riemers | |
| 26 | 2 | riemers | PUBLIC hUPS AS NEW Socket |
| 27 | 2 | riemers | PUBLIC tUPS AS Timer |
| 28 | 339 | rdnzl | PUBLIC sBuffer AS String |
| 29 | 2 | riemers | |
| 30 | 2 | riemers | PUBLIC SUB CheckUPS() |
| 31 | 2 | riemers | |
| 32 | 2 | riemers | DIM rResult AS Result |
| 33 | 2 | riemers | |
| 34 | 339 | rdnzl | TRY rResult = Main.hDB.Exec("SELECT * FROM devices WHERE interface = &1 AND enabled is TRUE", Devices.FindInterface("UPS Socket"))
|
| 35 | 339 | rdnzl | IF NOT ERROR THEN |
| 36 | 339 | rdnzl | IF rResult.Count THEN |
| 37 | 339 | rdnzl | FOR EACH rResult |
| 38 | 339 | rdnzl | IF bUPSDebug THEN Main.WriteDebugLog(("[UPS] checking UPS named '") & rResult!name & ("' with address '") & rResult!address & "'")
|
| 39 | 339 | rdnzl | Check(rResult!address, rResult!module) |
| 40 | 339 | rdnzl | NEXT |
| 41 | 339 | rdnzl | ELSE |
| 42 | 339 | rdnzl | Main.WriteLog(("UPS: no UPS(s) found in device table!"))
|
| 43 | 339 | rdnzl | END IF |
| 44 | 339 | rdnzl | END IF |
| 45 | 2 | riemers | |
| 46 | 2 | riemers | END |
| 47 | 2 | riemers | |
| 48 | 2 | riemers | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 49 | 2 | riemers | ' connect to the host:port |
| 50 | 2 | riemers | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 51 | 2 | riemers | PUBLIC FUNCTION Connect() AS Boolean |
| 52 | 2 | riemers | |
| 53 | 2 | riemers | ' try to close the connection |
| 54 | 2 | riemers | TRY hUPS.Close |
| 55 | 2 | riemers | |
| 56 | 2 | riemers | ' get a new one |
| 57 | 2 | riemers | hUPS = NEW Socket AS "UPS" |
| 58 | 245 | rdnzl | hUPS.Connect(sTCPHost, iTCPPort) |
| 59 | 2 | riemers | |
| 60 | 2 | riemers | ' all ok |
| 61 | 2 | riemers | RETURN TRUE |
| 62 | 2 | riemers | |
| 63 | 2 | riemers | CATCH ' some errors |
| 64 | 245 | rdnzl | Main.WriteLog(("UPS Error: ") & ERROR.Text)
|
| 65 | 2 | riemers | RETURN FALSE |
| 66 | 2 | riemers | |
| 67 | 2 | riemers | END |
| 68 | 2 | riemers | |
| 69 | 2 | riemers | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 70 | 2 | riemers | ' disconnect from the host |
| 71 | 2 | riemers | '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 72 | 2 | riemers | PUBLIC FUNCTION Disconnect() AS Boolean |
| 73 | 2 | riemers | |
| 74 | 2 | riemers | ' try to close the connection |
| 75 | 2 | riemers | TRY hUPS.Close |
| 76 | 245 | rdnzl | Main.WriteLog(("UPS socket close."))
|
| 77 | 2 | riemers | |
| 78 | 2 | riemers | ' all ok |
| 79 | 2 | riemers | RETURN TRUE |
| 80 | 2 | riemers | |
| 81 | 2 | riemers | CATCH ' some errors |
| 82 | 245 | rdnzl | Main.WriteLog(("UPS Error: ") & ERROR.Text)
|
| 83 | 2 | riemers | RETURN FALSE |
| 84 | 2 | riemers | |
| 85 | 2 | riemers | END |
| 86 | 2 | riemers | |
| 87 | 2 | riemers | PUBLIC SUB UPS_Error() |
| 88 | 2 | riemers | |
| 89 | 2 | riemers | ' handle error |
| 90 | 2 | riemers | SELECT CASE hUPS.Status |
| 91 | 2 | riemers | CASE Net.CannotCreateSocket |
| 92 | 454 | rdnzl | Main.WriteLog(("UPS: The system does not allow to create a socket."))
|
| 93 | 2 | riemers | CASE Net.HostNotFound |
| 94 | 454 | rdnzl | Main.WriteLog(("UPS: Host '") & sTCPHost & ("' not found."))
|
| 95 | 2 | riemers | CASE Net.ConnectionRefused |
| 96 | 454 | rdnzl | Main.WriteLog(("UPS: Unable to connect. Connection refused."))
|
| 97 | 2 | riemers | CASE Net.CannotRead |
| 98 | 454 | rdnzl | Main.WriteLog(("UPS: Error reading data."))
|
| 99 | 2 | riemers | CASE Net.CannotWrite |
| 100 | 454 | rdnzl | Main.WriteLog(("UPS: Error writing data."))
|
| 101 | 2 | riemers | END SELECT |
| 102 | 2 | riemers | |
| 103 | 2 | riemers | END |
| 104 | 2 | riemers | |
| 105 | 2 | riemers | PUBLIC SUB UPS_Read() |
| 106 | 2 | riemers | |
| 107 | 339 | rdnzl | DIM sData AS String |
| 108 | 339 | rdnzl | |
| 109 | 339 | rdnzl | TRY READ #hUPS, sData, 1 |
| 110 | 453 | rdnzl | IF ERROR THEN Main.WriteDebugLog(("[UPS] Error reading data from network socket! -> ") & Error.Text)
|
| 111 | 339 | rdnzl | IF sData = Chr(10) THEN ' buffer until newline then parse |
| 112 | 339 | rdnzl | IF Len(sBuffer) > 1 THEN ParseLine(sBuffer) |
| 113 | 339 | rdnzl | sBuffer = NULL |
| 114 | 339 | rdnzl | ELSE |
| 115 | 339 | rdnzl | sBuffer &= sData |
| 116 | 339 | rdnzl | END IF |
| 117 | 339 | rdnzl | |
| 118 | 339 | rdnzl | END |
| 119 | 339 | rdnzl | |
| 120 | 339 | rdnzl | PUBLIC SUB ParseLine(sBuf AS String) |
| 121 | 339 | rdnzl | |
| 122 | 339 | rdnzl | DIM sValue, sAddress AS String |
| 123 | 2 | riemers | DIM iDeviceId AS Integer |
| 124 | 2 | riemers | |
| 125 | 339 | rdnzl | IF bUPSDebug THEN Main.WriteDebugLog(sBuf) |
| 126 | 339 | rdnzl | |
| 127 | 339 | rdnzl | ' try to find address and deviceid |
| 128 | 339 | rdnzl | IF NOT InStr(sBuf, "ERR") THEN |
| 129 | 339 | rdnzl | sAddress = Replace(sBuf, "VAR ", "") |
| 130 | 339 | rdnzl | sAddress = Mid(sAddress, 1, InStr(sAddress, " ", 1) - 1) |
| 131 | 339 | rdnzl | iDeviceId = Devices.Find(sAddress, Devices.FindInterface("UPS Socket"), "UPS Device")
|
| 132 | 339 | rdnzl | END IF |
| 133 | 339 | rdnzl | |
| 134 | 2 | riemers | ' VAR smartups1000 input.voltage "223.6" |
| 135 | 2 | riemers | ' VAR smartups1000 ups.status "OL" |
| 136 | 61 | rdnzl | ' VAR smartups1000 ups.temperature "030.1" |
| 137 | 339 | rdnzl | ' VAR smartups1000 ups.load "41" |
| 138 | 339 | rdnzl | IF iDeviceId THEN |
| 139 | 339 | rdnzl | IF InStr(sBuf, "ups.status") THEN |
| 140 | 339 | rdnzl | IF InStr(sBuf, "OL") THEN |
| 141 | 339 | rdnzl | sValue = "Online" |
| 142 | 339 | rdnzl | ELSE IF InStr(sBuf, "OB") THEN |
| 143 | 339 | rdnzl | sValue = "On Battery" |
| 144 | 339 | rdnzl | ELSE IF InStr(sBuf, "LB") THEN |
| 145 | 339 | rdnzl | sValue = "Low Battery" |
| 146 | 339 | rdnzl | END IF |
| 147 | 339 | rdnzl | Devices.ValueUpdate(iDeviceId, sValue, "", "", "") |
| 148 | 339 | rdnzl | ELSE IF InStr(sBuf, "input.voltage") THEN |
| 149 | 339 | rdnzl | sValue = Mid$(sBuf, Len(sBuf) - 5, -1) |
| 150 | 339 | rdnzl | Devices.ValueUpdate(iDeviceId, "", sValue, "", "") |
| 151 | 526 | rdnzl | ELSE IF InStr(sBuf, "battery.charge") THEN |
| 152 | 526 | rdnzl | sValue = Mid$(sBuf, Len(sBuf) - 2, -1) |
| 153 | 526 | rdnzl | Devices.ValueUpdate(iDeviceId, "", sValue, "", "") |
| 154 | 339 | rdnzl | ELSE IF InStr(sBuf, "ups.temperature") THEN |
| 155 | 339 | rdnzl | sValue = Mid$(sBuf, Len(sBuf) - 4, -1) |
| 156 | 339 | rdnzl | Devices.ValueUpdate(iDeviceId, "", "", sValue, "") |
| 157 | 339 | rdnzl | ELSE IF InStr(sBuf, "ups.load") THEN |
| 158 | 339 | rdnzl | sValue = Mid$(sBuf, Len(sBuf) - 2, -1) |
| 159 | 339 | rdnzl | Devices.ValueUpdate(iDeviceId, "", "", sValue, "") |
| 160 | 2 | riemers | END IF |
| 161 | 2 | riemers | END IF |
| 162 | 2 | riemers | |
| 163 | 2 | riemers | END |
| 164 | 2 | riemers | |
| 165 | 2 | riemers | PUBLIC SUB UPS_Ready() |
| 166 | 2 | riemers | |
| 167 | 245 | rdnzl | Main.WriteLog(("UPS socket connected."))
|
| 168 | 2 | riemers | |
| 169 | 2 | riemers | ' start poll timer for UPS |
| 170 | 2 | riemers | tUPS = NEW Timer AS "tUPS" |
| 171 | 2 | riemers | tUPS.Delay = iPollTime * 1000 ' multiply for seconds |
| 172 | 2 | riemers | tUPS.Start |
| 173 | 2 | riemers | |
| 174 | 2 | riemers | END |
| 175 | 2 | riemers | |
| 176 | 2 | riemers | PUBLIC SUB tUPS_Timer() |
| 177 | 2 | riemers | |
| 178 | 2 | riemers | CheckUPS() |
| 179 | 2 | riemers | |
| 180 | 2 | riemers | END |
| 181 | 2 | riemers | |
| 182 | 339 | rdnzl | PUBLIC SUB Check(sAddress AS String, iModule AS Integer) |
| 183 | 2 | riemers | |
| 184 | 526 | rdnzl | DIM sCmd AS String = "GET VAR " & sAddress & " ups.status" |
| 185 | 2 | riemers | |
| 186 | 2 | riemers | IF bUPSDebug THEN Main.WriteDebugLog("[UPS] " & sCmd)
|
| 187 | 2 | riemers | TRY PRINT #hUPS, sCmd |
| 188 | 526 | rdnzl | IF ERROR THEN Main.WriteDebugLog(("[UPS] Error writing data to network socket! -> ") & Error.Text)
|
| 189 | 2 | riemers | sCmd = "GET VAR " & sAddress & " input.voltage" |
| 190 | 2 | riemers | IF bUPSDebug THEN Main.WriteDebugLog("[UPS] " & sCmd)
|
| 191 | 2 | riemers | TRY PRINT #hUPS, sCmd |
| 192 | 454 | rdnzl | IF ERROR THEN Main.WriteDebugLog(("[UPS] Error writing data to network socket! -> ") & Error.Text)
|
| 193 | 339 | rdnzl | |
| 194 | 526 | rdnzl | SELECT CASE Devices.FindDescrForDeviceType(iModule) |
| 195 | 526 | rdnzl | CASE "BackUPS" ' APC BackUPS |
| 196 | 339 | rdnzl | sCmd = "GET VAR " & sAddress & " ups.load" |
| 197 | 526 | rdnzl | CASE "MGE" ' MGE PC 675 |
| 198 | 526 | rdnzl | sCmd = "GET VAR " & sAddress & " battery.charge" |
| 199 | 526 | rdnzl | CASE ELSE ' APC SmartUPS |
| 200 | 339 | rdnzl | sCmd = "GET VAR " & sAddress & " ups.temperature" |
| 201 | 339 | rdnzl | END SELECT |
| 202 | 61 | rdnzl | IF bUPSDebug THEN Main.WriteDebugLog("[UPS] " & sCmd)
|
| 203 | 61 | rdnzl | TRY PRINT #hUPS, sCmd |
| 204 | 454 | rdnzl | IF ERROR THEN Main.WriteDebugLog(("[UPS] Error writing data to network socket! -> ") & Error.Text)
|
| 205 | 2 | riemers | |
| 206 | 2 | riemers | END |
| 207 | 2 | riemers | |
| 208 | 2 | riemers | ' implement properties |
| 209 | 2 | riemers | PRIVATE FUNCTION Host_Read() AS String |
| 210 | 2 | riemers | |
| 211 | 245 | rdnzl | RETURN sTCPHost |
| 212 | 2 | riemers | |
| 213 | 2 | riemers | END |
| 214 | 2 | riemers | |
| 215 | 2 | riemers | PRIVATE SUB Host_Write(Value AS String) |
| 216 | 2 | riemers | |
| 217 | 245 | rdnzl | sTCPHost = Value |
| 218 | 2 | riemers | |
| 219 | 2 | riemers | END |
| 220 | 2 | riemers | |
| 221 | 2 | riemers | PRIVATE FUNCTION Port_Read() AS Integer |
| 222 | 2 | riemers | |
| 223 | 245 | rdnzl | RETURN iTCPPort |
| 224 | 2 | riemers | |
| 225 | 2 | riemers | END |
| 226 | 2 | riemers | |
| 227 | 2 | riemers | PRIVATE SUB Port_Write(Value AS Integer) |
| 228 | 2 | riemers | |
| 229 | 245 | rdnzl | iTCPPort = Value |
| 230 | 2 | riemers | |
| 231 | 2 | riemers | END |
| 232 | 2 | riemers | |
| 233 | 2 | riemers | PRIVATE FUNCTION UPSDebug_Read() AS Boolean |
| 234 | 2 | riemers | |
| 235 | 2 | riemers | RETURN bUPSDebug |
| 236 | 2 | riemers | |
| 237 | 2 | riemers | END |
| 238 | 2 | riemers | |
| 239 | 2 | riemers | PRIVATE SUB UPSDebug_Write(Value AS Boolean) |
| 240 | 2 | riemers | |
| 241 | 2 | riemers | bUPSDebug = Value |
| 242 | 2 | riemers | |
| 243 | 2 | riemers | END |
| 244 | 2 | riemers | |
| 245 | 2 | riemers | PRIVATE FUNCTION PollTime_Read() AS Integer |
| 246 | 2 | riemers | |
| 247 | 2 | riemers | RETURN iPollTime |
| 248 | 2 | riemers | |
| 249 | 2 | riemers | END |
| 250 | 2 | riemers | |
| 251 | 2 | riemers | PRIVATE SUB PollTime_Write(Value AS Integer) |
| 252 | 2 | riemers | |
| 253 | 2 | riemers | iPollTime = Value |
| 254 | 2 | riemers | |
| 255 | 2 | riemers | END |
