// sketch to sniff PowerView packets from a pebble remote or hub #include #include #include #define SER_BAUDRATE (115200) RFPowerView powerView(RF_CE_PIN, RF_CS_PIN, RF_IRQ_PIN, RF_ID); void processBuffer(const uint8_t*); void processPacket(const Packet*); void printField(Field& field); void setup() { Serial.begin(SER_BAUDRATE); Serial.println("Starting up"); powerView.setPacketReceivedCallback(processPacket); powerView.setValidBufferReceivedCallback(processBuffer); if (!powerView.begin()) { Serial.println("Failed to start RFPowerView"); return; } Serial.println("Ready"); } void loop() { powerView.loop(); } void processBuffer(const uint8_t *buffer) { printBuffer(buffer); Serial.println(); } void processPacket(const Packet *packet) { if (std::holds_alternative(packet->header)) { auto header = std::get(packet->header); Serial.print("Source: "); Serial.print(header.source, HEX); } else if (std::holds_alternative(packet->header)) { auto header = std::get(packet->header); Serial.print("Source: "); Serial.print(header.source, HEX); Serial.print(" Destination: "); Serial.print(header.destination, HEX); } else if (std::holds_alternative(packet->header)) { auto header = std::get(packet->header); Serial.print("Source: "); Serial.print(header.source, HEX); Serial.print(" Groups: "); for (size_t i = 0; i < header.groups.size(); i++) { Serial.print(header.groups[i]); if (i != header.groups.size() - 1) { Serial.print(" "); } } } Serial.print(" "); Serial.print("Rolling codes: "); Serial.print(packet->rollingCode1, HEX); Serial.print(" "); Serial.print(packet->rollingCode2, HEX); Serial.print(" "); switch(packet->type) { case PacketType::STOP: Serial.print("Stop"); break; case PacketType::OPEN: Serial.print("Open"); break; case PacketType::CLOSE: Serial.print("Close"); break; case PacketType::OPEN_SLOW: Serial.print("Open Slow"); break; case PacketType::CLOSE_SLOW: Serial.print("Close Slow"); break; case PacketType::MOVE_TO_SAVED_POSITION: Serial.print("Move To Saved Position"); break; case PacketType::FIELDS: { FieldsParameters parameters = std::get(packet->parameters); for (size_t i = 0; i < parameters.fields.size(); i++) { Field field = parameters.fields[i]; printField(field); } break; } case PacketType::FIELD_COMMAND: { FieldsParameters parameters = std::get(packet->parameters); for (size_t i = 0; i < parameters.fields.size(); i++) { Field field = parameters.fields[i]; printField(field); } break; } case PacketType::UNKNOWN: Serial.print("???"); break; } Serial.println(); } void printField(Field& field) { if (field.type == FieldType::SET) { Serial.print("Set "); } if (field.type == FieldType::FETCH) { Serial.print("Fetch "); } switch (field.identifier) { case 0x50: { // position Serial.print("Position"); if (field.hasValue) { uint16_t value = std::get(field.value); uint8_t position = (uint8_t)std::round(((float)value / 0xFFFF) * 100); Serial.print("="); Serial.print(position); } break; } case 0x42: { // battery Serial.print("Battery"); if (field.hasValue) { uint8_t value = std::get(field.value); uint8_t battery = uint8_t(((float)value / 200) * 100); Serial.print("="); Serial.print(battery); } break; } default: { printUint8(field.identifier); if (field.hasValue) { if (std::holds_alternative(field.value)) { Serial.print("="); printUint8(std::get(field.value)); } else if (std::holds_alternative(field.value)) { Serial.print("="); printUint16(std::get(field.value)); } } } } Serial.print(" "); }