示例#1
0
void EnoceanDeviceContainer::handleTestRadioPacket(CompletedCB aCompletedCB, Esp3PacketPtr aEsp3PacketPtr, ErrorPtr aError)
{
  // ignore packets with error
  if (Error::isOK(aError)) {
    if (aEsp3PacketPtr->eepRorg()==rorg_RPS && aEsp3PacketPtr->radioDBm()>MIN_LEARN_DBM && enoceanComm.modemAppVersion()>0) {
      // uninstall handler
      enoceanComm.setRadioPacketHandler(NULL);
      // seen both watchdog response (modem works) and independent RPS telegram (RF is ok)
      LOG(LOG_NOTICE, "- enocean modem info: appVersion=0x%08X, apiVersion=0x%08X, modemAddress=0x%08X\n", enoceanComm.modemAppVersion(), enoceanComm.modemApiVersion(), enoceanComm.modemAddress());
      aCompletedCB(ErrorPtr());
      // done
      return;
    }
  }
  // - still waiting
  LOG(LOG_NOTICE, "- enocean test: still waiting for RPS telegram in learn distance\n");
}
示例#2
0
void EnoceanDevice::handleRadioPacket(Esp3PacketPtr aEsp3PacketPtr)
{
  ALOG(LOG_INFO, "now starts processing EnOcean packet:\n%s", aEsp3PacketPtr->description().c_str());
  lastPacketTime = MainLoop::now();
  lastRSSI = aEsp3PacketPtr->radioDBm();
  lastRepeaterCount = aEsp3PacketPtr->radioRepeaterCount();
  // pass to every channel
  for (EnoceanChannelHandlerVector::iterator pos = channels.begin(); pos!=channels.end(); ++pos) {
    (*pos)->handleRadioPacket(aEsp3PacketPtr);
  }
  // if device cannot be updated whenever output value change is requested, send updates after receiving a message
  if (pendingDeviceUpdate || updateAtEveryReceive) {
    // send updates, if any
    pendingDeviceUpdate = true; // set it in case of updateAtEveryReceive (so message goes out even if no changes pending)
    ALOG(LOG_NOTICE, "pending output update is now sent to device");
    sendOutgoingUpdate();
  }
}
示例#3
0
void EnoceanDeviceContainer::handleRadioPacket(Esp3PacketPtr aEsp3PacketPtr, ErrorPtr aError)
{
  if (aError) {
    LOG(LOG_INFO, "Radio packet error: %s\n", aError->description().c_str());
    return;
  }
  // check learning mode
  if (learningMode) {
    // no learn/unlearn actions detected so far
    // - check if we know that device address already. If so, it is a learn-out
    bool learnIn = enoceanDevices.find(aEsp3PacketPtr->radioSender())==enoceanDevices.end();
    // now add/remove the device (if the action is a valid learn/unlearn)
    // detect implicit (RPS) learn in only with sufficient radio strength (or explicit override of that check),
    // explicit ones are always recognized
    if (aEsp3PacketPtr->eepHasTeachInfo(disableProximityCheck ? 0 : MIN_LEARN_DBM, false)) {
      LOG(LOG_NOTICE, "Received EnOcean learn packet while learn mode enabled: %s\n", aEsp3PacketPtr->description().c_str());
      // This is actually a valid learn action
      ErrorPtr learnStatus;
      if (learnIn) {
        // new device learned in, add logical devices for it
        int numNewDevices = EnoceanDevice::createDevicesFromEEP(this, aEsp3PacketPtr->radioSender(), aEsp3PacketPtr->eepProfile(), aEsp3PacketPtr->eepManufacturer());
        if (numNewDevices>0) {
          // successfully learned at least one device
          // - update learn status (device learned)
          getDeviceContainer().reportLearnEvent(true, ErrorPtr());
        }
      }
      else {
        // device learned out, un-pair all logical dS devices it has represented
        // but keep dS level config in case it is reconnected
        unpairDevicesByAddress(aEsp3PacketPtr->radioSender(), false);
        getDeviceContainer().reportLearnEvent(false, ErrorPtr());
      }
      // - only allow one learn action (to prevent learning out device when
      //   button is released or other repetition of radio packet)
      learningMode = false;
    } // learn action
  }
  else {
    // not learning mode, dispatch packet to all devices known for that address
    for (EnoceanDeviceMap::iterator pos = enoceanDevices.lower_bound(aEsp3PacketPtr->radioSender()); pos!=enoceanDevices.upper_bound(aEsp3PacketPtr->radioSender()); ++pos) {
      if (aEsp3PacketPtr->eepHasTeachInfo(MIN_LEARN_DBM, false) && aEsp3PacketPtr->eepRorg()!=rorg_RPS) {
        // learning packet in non-learn mode -> report as non-regular user action, may be attempt to identify a device
        // Note: RPS devices are excluded because for these all telegrams are regular regular user actions. signalDeviceUserAction() will be called
        //   from button
        if (getDeviceContainer().signalDeviceUserAction(*(pos->second), false)) {
          // consumed for device identification purposes, suppress further processing
          break;
        }
      }
      // handle regularily (might be RPS switch which does not have separate learn/action packets
      pos->second->handleRadioPacket(aEsp3PacketPtr);
    }
  }
}
示例#4
0
void EnoceanRemoteControlDevice::buttonAction(bool aRight, bool aUp, bool aPress)
{
  FOCUSLOG("- %s simulated %s %s button", aPress ? "PRESSING" : "RELEASING", aRight ? "RIGHT" : "LEFT", aUp ? "UP" : "DOWN");
  Esp3PacketPtr packet = Esp3PacketPtr(new Esp3Packet());
  packet->initForRorg(rorg_RPS);
  packet->setRadioDestination(EnoceanBroadcast);
  if (aPress) {
    uint8_t d = 0x10; // energy bow: pressed
    if (aUp) d |= 0x20; // "up"
    if (aRight) d |= 0x40; // B = right button
    packet->radioUserData()[0] = d;
    packet->setRadioStatus(status_NU|status_T21); // pressed
  }
  else {
    packet->radioUserData()[0] = 0x00; // release
    packet->setRadioStatus(status_T21); // released
  }
  packet->setRadioSender(getAddress()); // my own ID base derived address that is learned into this actor
  getEnoceanDeviceContainer().enoceanComm.sendCommand(packet, NULL);
}