Details | Last modification | View Log | SVN | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 15 | arune | 1 | /* |
| 2 | * File created by arune |
||
| 3 | * at 2004-jan-02 18:00:08 |
||
| 4 | */ |
||
| 5 | package Macbeth.Modules.modTempFetcher; |
||
| 6 | |||
| 7 | import javax.swing.*; |
||
| 8 | import java.awt.*; |
||
| 9 | import java.awt.event.*; |
||
| 10 | import java.util.HashMap; |
||
| 11 | import java.util.Iterator; |
||
| 12 | import java.math.BigDecimal; |
||
| 13 | import java.io.*; |
||
| 14 | |||
| 15 | |||
| 16 | import Macbeth.System.*; |
||
| 17 | import Macbeth.Utilities.UByte; |
||
| 18 | import Macbeth.Utilities.MyDateTime; |
||
| 19 | import Macbeth.Utilities.DataRepository; |
||
| 20 | import Macbeth.XML.XMLDataHandler; |
||
| 21 | |||
| 22 | /** |
||
| 23 | * |
||
| 24 | * |
||
| 25 | * |
||
| 26 | * |
||
| 27 | * |
||
| 28 | * |
||
| 29 | * @author arune |
||
| 30 | * @version 1.0 |
||
| 31 | */ |
||
| 32 | |||
| 33 | public class modTempFetcher extends MbModule { //implements MbModuleGUI { |
||
| 34 | //The sensordata that we receive via XML |
||
| 35 | private UByte[] receivedBytes; |
||
| 36 | //Interval between the data collecting. default frequency is every 60th second |
||
| 37 | private int timerInterval = 60; |
||
| 38 | private int nrOfSamples = 0; |
||
| 39 | //our data request timer |
||
| 40 | private Timer requestDataTimer; |
||
| 41 | |||
| 42 | private HashMap sensors; |
||
| 43 | |||
| 44 | private HashMap sensorNodes; |
||
| 45 | |||
| 46 | private boolean parsingARNEXML; |
||
| 47 | |||
| 48 | //A GUI for our module. |
||
| 49 | private GUI gui; |
||
| 50 | //Is our GUI currently visible or not? |
||
| 51 | private boolean guiVisible = false; |
||
| 52 | |||
| 53 | /** |
||
| 54 | * Creates a new instance of modTempFetcher. |
||
| 55 | */ |
||
| 56 | public modTempFetcher() { |
||
| 57 | //construct MbModule |
||
| 58 | super(); |
||
| 59 | //todo: ? |
||
| 60 | receivedBytes = new UByte[6]; |
||
| 61 | parsingARNEXML = false; |
||
| 62 | gui = new GUI(); |
||
| 63 | requestDataTimer = null; |
||
| 64 | sensors = new HashMap(8); |
||
| 65 | sensorNodes = new HashMap(8); |
||
| 66 | //we depend on the ARNE-module |
||
| 67 | addDependency("ARNE"); |
||
| 68 | //register our packet data handler |
||
| 69 | setPacketDataHandler(new PacketDataHandler()); |
||
| 70 | } |
||
| 71 | |||
| 72 | /** |
||
| 73 | * Gets the name of the component. |
||
| 74 | * @return The name of the component. |
||
| 75 | */ |
||
| 76 | public String name() { |
||
| 77 | return "TempFetcher"; |
||
| 78 | } |
||
| 79 | |||
| 80 | /** |
||
| 81 | * Gets the description of the component. |
||
| 82 | * @return The description of the component. |
||
| 83 | */ |
||
| 84 | public String description() { |
||
| 85 | return "Collects temperature data from ARNE bus"; |
||
| 86 | } |
||
| 87 | |||
| 88 | /** |
||
| 89 | * This method sets default values on all _required_ data |
||
| 90 | * fields in the data repository. |
||
| 91 | */ |
||
| 92 | protected void initDataFields() { |
||
| 93 | options.putField("timerinterval", "60"); |
||
| 94 | options.putField("samples", "5"); |
||
| 95 | } |
||
| 96 | |||
| 97 | /** |
||
| 98 | * Starts up this module. |
||
| 99 | */ |
||
| 100 | public void startup() throws MbStartupException { |
||
| 101 | //start up MbModule |
||
| 102 | super.startup(); |
||
| 103 | //get options from data repository |
||
| 104 | timerInterval = Integer.parseInt(options.getField("timerinterval")); |
||
| 105 | nrOfSamples = Integer.parseInt(options.getField("samples")); |
||
| 106 | |||
| 107 | if (timerInterval > 0) { |
||
| 108 | TimerListener lyssnare = new TimerListener(); |
||
| 109 | requestDataTimer = new Timer(1000 * timerInterval, lyssnare); |
||
| 110 | requestDataTimer.start(); |
||
| 111 | } |
||
| 112 | |||
| 113 | if (nrOfSamples <= 0) { |
||
| 114 | nrOfSamples = 1; //to not cause div by 0 |
||
| 115 | } |
||
| 116 | |||
| 117 | DataRepository.DataList list = dataRepository.getList("sensors"); |
||
| 118 | Iterator it = list.items(); |
||
| 119 | while (it.hasNext()) { |
||
| 120 | DataRepository.DataListItem item = (DataRepository.DataListItem) it.next(); |
||
| 121 | String sensorName = item.getField("name"); |
||
| 122 | String sensorLogPath = item.getField("logpath"); |
||
| 123 | UByte sensorIdentByte = UByte.parseUByte(item.getField("identbyte")); |
||
| 124 | boolean printToDisplay = Boolean.valueOf(item.getField("printtodisplay")).booleanValue(); |
||
| 125 | sensors.put(sensorName, new TempSensor(sensorName, sensorIdentByte, sensorLogPath, nrOfSamples, printToDisplay)); |
||
| 126 | } |
||
| 127 | |||
| 128 | list = dataRepository.getList("sensornodes"); |
||
| 129 | it = list.items(); |
||
| 130 | while (it.hasNext()) { |
||
| 131 | DataRepository.DataListItem item = (DataRepository.DataListItem) it.next(); |
||
| 132 | String nodeName = item.getField("name"); |
||
| 133 | sensorNodes.put(nodeName, nodeName); |
||
| 134 | } |
||
| 135 | |||
| 136 | |||
| 137 | } |
||
| 138 | |||
| 139 | /** |
||
| 140 | * Shuts down this module. |
||
| 141 | */ |
||
| 142 | public void shutdown() { |
||
| 143 | //stop timer if it's running |
||
| 144 | if (requestDataTimer!=null) { |
||
| 145 | if (requestDataTimer.isRunning()) { |
||
| 146 | requestDataTimer.stop(); |
||
| 147 | } |
||
| 148 | } |
||
| 149 | //shut down MbModule |
||
| 150 | super.shutdown(); |
||
| 151 | } |
||
| 152 | |||
| 153 | |||
| 154 | |||
| 155 | private void handleSensor(UByte[] bytes, int index) { |
||
| 156 | final int D1 = -40; final double D2 = 0.01; |
||
| 157 | //start searching on index |
||
| 158 | //match first byte (byte index) with any of the sensors identbyte |
||
| 159 | if (!sensors.isEmpty()) { |
||
| 160 | TempSensor actualSensor = null; |
||
| 161 | Iterator it = sensors.keySet().iterator(); |
||
| 162 | while (it.hasNext()) { |
||
| 163 | //_debug.println("handleSensor, looping through sensors"); |
||
| 164 | String key = (String) it.next(); |
||
| 165 | TempSensor f = (TempSensor) sensors.get(key); |
||
| 166 | if (f != null) { |
||
| 167 | //_debug.println("handleSensor, f:" + f.identByte + " bytes[index]: " + bytes[index]); |
||
| 168 | if (f.identByte.equals(bytes[index])) { |
||
| 169 | //_debug.println("handleSensor, found an actualSensor"); |
||
| 170 | actualSensor = f; |
||
| 171 | } |
||
| 172 | } |
||
| 173 | } |
||
| 174 | |||
| 175 | if (actualSensor != null) { |
||
| 176 | |||
| 177 | int iTemperature = bytes[index+1].shortValue() * 256; |
||
| 178 | iTemperature = iTemperature + bytes[index+2].shortValue(); |
||
| 179 | double dTemp = (iTemperature * D2) + D1; |
||
| 180 | //_debug.println(actualSensor.name + " temperature is " + dTemp); |
||
| 181 | if (actualSensor.addValue(dTemp)) { //add value and check if ready to get mean |
||
| 182 | double dMeanTemp = actualSensor.getMean(); |
||
| 183 | double dTempRadix2 = round(dMeanTemp, 2); |
||
| 184 | double dTempRadix1 = round(dMeanTemp, 1); |
||
| 185 | |||
| 186 | //kolla actualSensor.printToDisplay, om true ska paket skickas till display |
||
| 187 | //data = actualSensor.name " " dTempRadix1 |
||
| 188 | //obs id, ttl osv! |
||
| 189 | //todo: perhaps change id to something based on actualSensor.identbyte? |
||
| 190 | if (actualSensor.printToDisplay) { |
||
| 191 | MbPacket p = new MbPacket(); |
||
| 192 | //p.setDestination(new MbLocation("self","PacketReceiver")); |
||
| 193 | p.setDestination(new MbLocation("self","SmallDisplays")); |
||
| 194 | //ARNE packet in XML-format |
||
| 195 | //todo: byt ut gradertecknet mot ° eller nĺt |
||
| 196 | p.setContents(" <lcdpacket sender=\"" + name() |
||
| 197 | + "\" type=\"textrow\" prio=\"1\" ttl=\"0\" id=\"458328\" data=\"" |
||
| 198 | + actualSensor.name + " " + dTempRadix1 + "Ă" |
||
| 199 | + "\" />"); |
||
| 200 | sendPacket(p); |
||
| 201 | } |
||
| 202 | |||
| 203 | //_debug.println("Printing " + dTempRadix1 + " at " + actualSensor.logPath); |
||
| 204 | printToFile(dTempRadix1, dTempRadix2, actualSensor.logPath); |
||
| 205 | } |
||
| 206 | } |
||
| 207 | } |
||
| 208 | |||
| 209 | } |
||
| 210 | |||
| 211 | private void handleBytes(UByte[] bytes) { |
||
| 212 | //_debug.println("handleBytes, bytes.length: " + bytes.length); |
||
| 213 | if ((bytes.length % 3 == 0) && (bytes.length > 0)) { |
||
| 214 | //_debug.println("handleBytes, mod ok"); |
||
| 215 | for (int i = 0; i < bytes.length; i = i + 3) { |
||
| 216 | //_debug.println("handleBytes, calls handleSensor with i = " + i); |
||
| 217 | handleSensor(bytes, i); |
||
| 218 | } |
||
| 219 | } |
||
| 220 | } |
||
| 221 | |||
| 222 | |||
| 223 | private void printToFile(double dataValue1, double dataValue2, String folderPath) { |
||
| 224 | //create log output stream |
||
| 225 | PrintStream log; |
||
| 226 | try { |
||
| 227 | //Date UTCTime = Date.valueOf("2004-01-08"); |
||
| 228 | long UTCTime = System.currentTimeMillis(); |
||
| 229 | String date = Long.toString(UTCTime); |
||
| 230 | |||
| 231 | log = new PrintStream(new FileOutputStream(folderPath + "\\datetemphumid")); |
||
| 232 | //log.println(MyDateTime.now("yyyy-MM-dd HH:mm:ss")); |
||
| 233 | log.println(date.substring(0, date.length()-3)); |
||
| 234 | log.println(doubleToStringSpecial(dataValue2)); |
||
| 235 | log.flush(); |
||
| 236 | log.close(); |
||
| 237 | log = new PrintStream(new FileOutputStream(folderPath + "\\temperature")); |
||
| 238 | log.println(doubleToStringSpecial(dataValue2)); |
||
| 239 | log.flush(); |
||
| 240 | log.close(); |
||
| 241 | log = new PrintStream(new FileOutputStream(folderPath + "\\temperature_rd")); |
||
| 242 | log.println(doubleToStringSpecial(dataValue1)); |
||
| 243 | log.flush(); |
||
| 244 | log.close(); |
||
| 245 | log = new PrintStream(new FileOutputStream(folderPath + "\\formated_rd")); |
||
| 246 | log.println(" "); |
||
| 247 | log.println(doubleToStringSpecial(dataValue1)); |
||
| 248 | log.flush(); |
||
| 249 | log.close(); |
||
| 250 | log = new PrintStream(new FileOutputStream(folderPath + "\\all-log.txt", true)); |
||
| 251 | log.println(MyDateTime.now("yyyy-MM-dd HH:mm:ss ") + |
||
| 252 | doubleToStringSpecial(dataValue2)); |
||
| 253 | log.flush(); |
||
| 254 | log.close(); |
||
| 255 | log = new PrintStream(new FileOutputStream(folderPath + "\\datetime")); |
||
| 256 | log.println(MyDateTime.now("yyyy-MM-dd HH:mm:ss")); |
||
| 257 | log.flush(); |
||
| 258 | log.close(); |
||
| 259 | } catch (FileNotFoundException e) { |
||
| 260 | _errors.println("Path not found, " + folderPath); |
||
| 261 | } |
||
| 262 | } |
||
| 263 | |||
| 264 | public static String doubleToStringSpecial(double value) { |
||
| 265 | return Double.toString(value).replace('.',','); |
||
| 266 | } |
||
| 267 | |||
| 268 | |||
| 269 | public static double round(double value, int radix) { |
||
| 270 | BigDecimal bd; |
||
| 271 | bd = new BigDecimal(value); |
||
| 272 | bd = bd.setScale(radix,BigDecimal.ROUND_HALF_UP); |
||
| 273 | return bd.doubleValue(); |
||
| 274 | } |
||
| 275 | |||
| 276 | |||
| 277 | /** |
||
| 278 | * Takes care of XML-data found in incoming packets. |
||
| 279 | */ |
||
| 280 | private class PacketDataHandler implements XMLDataHandler { |
||
| 281 | /** |
||
| 282 | * Called when start of a new element is found in the XML-data. |
||
| 283 | * Ex: <name attr1="value1" attr2="value2"> |
||
| 284 | * Element name would then be "name" and attribute list |
||
| 285 | * would contain "value1" and "value2" mapped to the attribute |
||
| 286 | * names "attr1" and "attr2". |
||
| 287 | * @param element The name of the element. |
||
| 288 | * @param attributes The element attributes. |
||
| 289 | */ |
||
| 290 | public void XMLstartElement(String element, HashMap attributes) { |
||
| 291 | //Ex: <arnepacket bytes="6"> |
||
| 292 | if (element.equals("arnepacket") && attributes.containsKey("bytes")) { |
||
| 293 | int bytes = Integer.parseInt((String)attributes.get("bytes")); |
||
| 294 | //we should always get six bytes from TempNode ('H' RHh RHl 'T' Th Tl) |
||
| 295 | // if (bytes==6) { |
||
| 296 | parsingARNEXML = true; |
||
| 297 | receivedBytes = new UByte[bytes]; |
||
| 298 | // } else { |
||
| 299 | // _errors.println("invalid number of bytes in ARNE packet"); |
||
| 300 | // } |
||
| 301 | } |
||
| 302 | //Ex: <byte id="1" value="5" /> |
||
| 303 | else if (element.equals("byte") && attributes.containsKey("id") && attributes.containsKey("value")) { |
||
| 304 | if (parsingARNEXML) { |
||
| 305 | short id = Short.parseShort(attributes.get("id").toString()); |
||
| 306 | //if id is valid |
||
| 307 | if (id>0 && id<=receivedBytes.length) { |
||
| 308 | //remember byte |
||
| 309 | receivedBytes[id-1] = UByte.parseUByte((String)attributes.get("value")); |
||
| 310 | } else { |
||
| 311 | _errors.println("invalid byte IDs specified"); |
||
| 312 | parsingARNEXML = false; |
||
| 313 | } |
||
| 314 | } else { |
||
| 315 | _errors.println("byte-attribute found outside arnepacket-attribute"); |
||
| 316 | } |
||
| 317 | } |
||
| 318 | } |
||
| 319 | |||
| 320 | /** |
||
| 321 | * Called when end of an element was found in the XML-data. |
||
| 322 | * Ex: </name> or <test attr="value" /> |
||
| 323 | * @param element The name of the element. |
||
| 324 | */ |
||
| 325 | public void XMLendElement(String element) { |
||
| 326 | //Ex: </arnepacket> |
||
| 327 | if (element.equals("arnepacket")) { |
||
| 328 | if (parsingARNEXML) { |
||
| 329 | parsingARNEXML = false; |
||
| 330 | //handle our received bytes now |
||
| 331 | handleBytes(receivedBytes); |
||
| 332 | } |
||
| 333 | } |
||
| 334 | } |
||
| 335 | |||
| 336 | public void XMLelementData(String data) {} |
||
| 337 | public void XMLdocumentStart() {} |
||
| 338 | public void XMLdocumentEnd() {} |
||
| 339 | } |
||
| 340 | |||
| 341 | |||
| 342 | /** |
||
| 343 | * Will be called when our GUI should be shown. |
||
| 344 | */ |
||
| 345 | public void renderGUI(Container drawArea) { |
||
| 346 | gui.render(drawArea); |
||
| 347 | } |
||
| 348 | |||
| 349 | /** |
||
| 350 | * A class for our GUI. |
||
| 351 | */ |
||
| 352 | class GUI implements ActionListener { |
||
| 353 | |||
| 354 | public void render(Container renderArea) { |
||
| 355 | //renderArea.setPreferredSize(150, 200); |
||
| 356 | renderArea.setLayout(new GridLayout(200,1)); |
||
| 357 | |||
| 358 | /*btnLampButtons = new JButton[roomObjects.size()]; |
||
| 359 | Iterator it = roomObjects.keySet().iterator(); |
||
| 360 | int i=0; |
||
| 361 | while (it.hasNext()) { |
||
| 362 | RoomObject o = (RoomObject)roomObjects.get((String)it.next()); |
||
| 363 | if (o!=null) { |
||
| 364 | btnLampButtons[i] = new JButton(o.name); |
||
| 365 | btnLampButtons[i].setActionCommand("roomobject:" + o.name); |
||
| 366 | btnLampButtons[i].addActionListener(this); |
||
| 367 | renderArea.add(btnLampButtons[i]); |
||
| 368 | i++; |
||
| 369 | } |
||
| 370 | }*/ |
||
| 371 | } |
||
| 372 | |||
| 373 | public void actionPerformed(ActionEvent e) { |
||
| 374 | //was this a room object-button press? |
||
| 375 | /*if (e.getActionCommand().startsWith("roomobject:")) { |
||
| 376 | //split its actioncommand to find out which lamp it was for |
||
| 377 | String[] tokens = e.getActionCommand().split("roomobject:"); |
||
| 378 | //try to find a room object with this name |
||
| 379 | RoomObject o = (RoomObject)roomObjects.get(tokens[1]); |
||
| 380 | //if found |
||
| 381 | if (o!=null) { |
||
| 382 | //toggle corresponding room object |
||
| 383 | toggleRoomObject(o.byteValue.shortValue()); |
||
| 384 | } |
||
| 385 | }*/ |
||
| 386 | } |
||
| 387 | } |
||
| 388 | |||
| 389 | //En lyssnare för timern |
||
| 390 | private class TimerListener implements ActionListener { |
||
| 391 | |||
| 392 | // public TimerLyssnare() |
||
| 393 | // { |
||
| 394 | // } |
||
| 395 | |||
| 396 | public void actionPerformed(ActionEvent e) { |
||
| 397 | if (!sensorNodes.isEmpty()) { |
||
| 398 | Iterator it = sensorNodes.keySet().iterator(); |
||
| 399 | while (it.hasNext()) { |
||
| 400 | //_debug.println("timerevent, looping through sensorNodes"); |
||
| 401 | String f = (String) it.next(); |
||
| 402 | //String f = (String) sensorNodes.get(key); |
||
| 403 | if (f != null) { |
||
| 404 | MbPacket p = new MbPacket(); |
||
| 405 | p.setDestination(new MbLocation("self", "ARNE")); |
||
| 406 | p.setContents( "<arnepacket bytes=\"6\" destnode=\"" + f + "\">" + |
||
| 407 | "<byte id=\"1\" value=\"65\"/>" + // send 'A', addressing |
||
| 408 | "<byte id=\"2\" value=\"64\"/>" + // send PC-node-address 0x40 |
||
| 409 | "<byte id=\"3\" value=\"0\"/>" + // send PC-Host 0x00 |
||
| 410 | "<byte id=\"4\" value=\"85\"/>" + // send PC-Module 0x55 |
||
| 411 | "<byte id=\"5\" value=\"68\"/>" + // send 'D', data none |
||
| 412 | "<byte id=\"6\" value=\"80\"/>" + // send 'P' for poll |
||
| 413 | "</arnepacket>"); |
||
| 414 | sendPacket(p); |
||
| 415 | |||
| 416 | } |
||
| 417 | } |
||
| 418 | } |
||
| 419 | } |
||
| 420 | } |
||
| 421 | } |