public SpineObject decode(Node node, byte[] payload) throws PacketDecodingException { BufferedRawData data = new BufferedRawData(); data.baseInit(node, payload); // data.setFunctionCode(SPINEFunctionConstants.BUFFERED_RAW_DATA); short pldIndex = 2; byte sensorCode = (byte) (payload[pldIndex] >> 4); data.setSensorCode(sensorCode); byte channelBitmask = (byte) (payload[pldIndex++] & 0x0F); data.setChannelBitmask(channelBitmask); byte dataWordLength = payload[pldIndex++]; data.setDataWordLength(dataWordLength); pldIndex++; // skip MSB of the bufferSize because it will be always 0 int bufferSize = payload[pldIndex++]; int[][] values = new int[SPINESensorConstants.MAX_VALUE_TYPES][]; // if the actual sensor readings data ((payload.length - pldIndex) bytes) // in the payload is less than what is declared (by channelBitmask, bufferSize, and // dataWordLength) // then this message is somehow malformed or corrupted. if (((payload.length - pldIndex) < (SPINESensorConstants.countChannelsInBitmask(channelBitmask) * bufferSize * dataWordLength))) throw new PacketDecodingException( "Malformed or corrupted BufferedRawData message received " + "[from node: " + node.getPhysicalID() + "]"); byte[] dataTmp = new byte[4]; for (int i = 0; i < SPINESensorConstants.MAX_VALUE_TYPES; i++) { if (SPINESensorConstants.chPresent(i, channelBitmask)) { values[i] = new int[bufferSize]; for (int j = bufferSize - 1; j >= 0; j--) { if (dataWordLength == 1) { dataTmp[3] = payload[pldIndex++]; dataTmp[2] = 0; dataTmp[1] = 0; dataTmp[0] = 0; } else if (dataWordLength == 2) { dataTmp[3] = payload[pldIndex++]; dataTmp[2] = payload[pldIndex++]; dataTmp[1] = 0; dataTmp[0] = 0; } else if (dataWordLength == 3) { dataTmp[3] = payload[pldIndex++]; dataTmp[2] = payload[pldIndex++]; dataTmp[1] = payload[pldIndex++]; dataTmp[0] = 0; } else if (dataWordLength == 4) { dataTmp[3] = payload[pldIndex++]; dataTmp[2] = payload[pldIndex++]; dataTmp[1] = payload[pldIndex++]; dataTmp[0] = payload[pldIndex++]; } values[i][j] = Data.convertFourBytesToInt(dataTmp, 0); } } } data.setValues(values); return data; }
public void discoveryCompleted(Vector activeNodes) { // we loop over the discovered nodes (hopefully, at least a node's showed up!) Node curr = null; for (int j = 0; j < activeNodes.size(); j++) { curr = (Node) activeNodes.elementAt(j); // we print for each node its details (nodeID, sensors and functions provided) System.out.println(curr); // for each node, we look for specific services for (int i = 0; i < curr.getSensorsList().size(); i++) { byte sensor = ((Sensor) curr.getSensorsList().elementAt(i)).getCode(); // if the current node has an accelerometer, then... if (sensor == SPINESensorConstants.ACC_SENSOR) { // ... we first setup that sensor, specifying its sampling time and time scale; then ... SpineSetupSensor sss = new SpineSetupSensor(); sss.setSensor(sensor); sss.setTimeScale(SPINESensorConstants.MILLISEC); sss.setSamplingTime(SAMPLING_TIME); manager.setup(curr, sss); // ... we can setup a specific function (in this case a Feature) on that sensor; then ... FeatureSpineSetupFunction ssf = new FeatureSpineSetupFunction(); ssf.setSensor(sensor); ssf.setWindowSize(WINDOW_SIZE); ssf.setShiftSize(SHIFT_SIZE); manager.setup(curr, ssf); // ... we can activate that function with function specific parameters // (for Feature they are the desired feature extractors); we can also ... FeatureSpineFunctionReq sfr = new FeatureSpineFunctionReq(); sfr.setSensor(sensor); sfr.add( new Feature( SPINEFunctionConstants.MODE, ((Sensor) curr.getSensorsList().elementAt(i)).getChannelBitmask())); sfr.add( new Feature( SPINEFunctionConstants.MEDIAN, ((Sensor) curr.getSensorsList().elementAt(i)).getChannelBitmask())); sfr.add( new Feature( SPINEFunctionConstants.MAX, ((Sensor) curr.getSensorsList().elementAt(i)).getChannelBitmask())); sfr.add( new Feature( SPINEFunctionConstants.MIN, ((Sensor) curr.getSensorsList().elementAt(i)).getChannelBitmask())); manager.activate(curr, sfr); // ... split a more complex activation in multiple activations // (if the specific function implementation in the node side allows that); of course we // always can ... sfr = new FeatureSpineFunctionReq(); sfr.setSensor(sensor); sfr.add( new Feature( SPINEFunctionConstants.MEAN, ((Sensor) curr.getSensorsList().elementAt(i)).getChannelBitmask())); sfr.add( new Feature( SPINEFunctionConstants.AMPLITUDE, ((Sensor) curr.getSensorsList().elementAt(i)).getChannelBitmask())); manager.activate(curr, sfr); // SetUp Alarm Engine // Window and Shift may be set to value different from the feature engine ones. // here we use the same values for debigging proposes AlarmSpineSetupFunction ssf2 = new AlarmSpineSetupFunction(); ssf2.setSensor(sensor); ssf2.setWindowSize(WINDOW_SIZE); ssf2.setShiftSize(SHIFT_SIZE); manager.setup(curr, ssf2); // Activate alarm on MAX value (one of the features computed above) on CH1 // alarm sent when MAX > upperThresold AlarmSpineFunctionReq sfr2 = new AlarmSpineFunctionReq(); int lowerThreshold = 20; int upperThreshold = 40; sfr2.setDataType(SPINEFunctionConstants.MAX); sfr2.setSensor(SPINESensorConstants.ACC_SENSOR); sfr2.setValueType((SPINESensorConstants.CH1_ONLY)); sfr2.setLowerThreshold(lowerThreshold); sfr2.setUpperThreshold(upperThreshold); sfr2.setAlarmType(SPINEFunctionConstants.ABOVE_THRESHOLD); manager.activate(curr, sfr2); // Activate alarm on AMPLITUDE value (one of the features computed above) on CH2 // alarm sent when AMPLITUDE < lowerThreshold lowerThreshold = 2000; upperThreshold = 1000; sfr2.setDataType(SPINEFunctionConstants.AMPLITUDE); sfr2.setSensor(SPINESensorConstants.ACC_SENSOR); sfr2.setValueType((SPINESensorConstants.CH2_ONLY)); sfr2.setLowerThreshold(lowerThreshold); sfr2.setUpperThreshold(upperThreshold); sfr2.setAlarmType(SPINEFunctionConstants.BELOW_THRESHOLD); manager.activate(curr, sfr2); } // repeat this process for other desired sensors; after that we can finally ... else if (sensor == SPINESensorConstants.INTERNAL_TEMPERATURE_SENSOR) { SpineSetupSensor sss = new SpineSetupSensor(); sss.setSensor(sensor); sss.setTimeScale(SPINESensorConstants.MILLISEC); sss.setSamplingTime(OTHER_SAMPLING_TIME); manager.setup(curr, sss); FeatureSpineSetupFunction ssf = new FeatureSpineSetupFunction(); ssf.setSensor(sensor); ssf.setWindowSize(OTHER_WINDOW_SIZE); ssf.setShiftSize(OTHER_SHIFT_SIZE); manager.setup(curr, ssf); FeatureSpineFunctionReq sfr = new FeatureSpineFunctionReq(); sfr.setSensor(sensor); sfr.add( new Feature( SPINEFunctionConstants.MODE, ((Sensor) curr.getSensorsList().elementAt(i)).getChannelBitmask())); sfr.add( new Feature( SPINEFunctionConstants.MEDIAN, ((Sensor) curr.getSensorsList().elementAt(i)).getChannelBitmask())); sfr.add( new Feature( SPINEFunctionConstants.MAX, ((Sensor) curr.getSensorsList().elementAt(i)).getChannelBitmask())); sfr.add( new Feature( SPINEFunctionConstants.MIN, ((Sensor) curr.getSensorsList().elementAt(i)).getChannelBitmask())); manager.activate(curr, sfr); // SetUp Alarm Engine // Same Window and Shift as before AlarmSpineSetupFunction ssf3 = new AlarmSpineSetupFunction(); ssf3.setSensor(sensor); ssf3.setWindowSize(WINDOW_SIZE); ssf3.setShiftSize(SHIFT_SIZE); manager.setup(curr, ssf3); // Activate alarm on MIN value (one of the features computed above)on CH1 // alarm sent when lowerThreshold < MIN < upperThreshold AlarmSpineFunctionReq sfr3 = new AlarmSpineFunctionReq(); int lowerThreshold = 1000; int upperThreshold = 3000; sfr3.setDataType(SPINEFunctionConstants.MIN); sfr3.setSensor(sensor); sfr3.setValueType((SPINESensorConstants.CH1_ONLY)); sfr3.setLowerThreshold(lowerThreshold); sfr3.setUpperThreshold(upperThreshold); sfr3.setAlarmType(SPINEFunctionConstants.IN_BETWEEN_THRESHOLDS); manager.activate(curr, sfr3); } } } // ... start the sensor network sensing and computing our aforeactivated services. if (activeNodes.size() > 0) manager.startWsn( true, true); // we can tune a few node parameters at run-time for reducing the power consumption // and the packets drop. }