/** * Handle a RDM message. */ void SimpleE133Controller::HandlePacket( const ola::e133::E133RDMMessage &rdm_message) { OLA_INFO << "RDM callback executed with code: " << ola::rdm::ResponseCodeToString(rdm_message.response_code); m_ss.Terminate(); if (rdm_message.response_code != ola::rdm::RDM_COMPLETED_OK) return; switch (rdm_message.response->ResponseType()) { case ola::rdm::RDM_NACK_REASON: HandleNack(rdm_message.response); return; default: break; } const RDMResponse *response = rdm_message.response; const ola::rdm::PidDescriptor *pid_descriptor = m_pid_helper->GetDescriptor( response->ParamId(), response->SourceUID().ManufacturerId()); const ola::messaging::Descriptor *descriptor = NULL; if (pid_descriptor) { switch (response->CommandClass()) { case ola::rdm::RDMCommand::GET_COMMAND_RESPONSE: descriptor = pid_descriptor->GetResponse(); break; case ola::rdm::RDMCommand::SET_COMMAND_RESPONSE: descriptor = pid_descriptor->SetResponse(); break; default: OLA_WARN << "Unknown command class " << response->CommandClass(); } } auto_ptr<const ola::messaging::Message> message; if (descriptor) message.reset(m_pid_helper->DeserializeMessage(descriptor, response->ParamData(), response->ParamDataSize())); if (message.get()) cout << m_pid_helper->PrettyPrintMessage( response->SourceUID().ManufacturerId(), response->CommandClass() == ola::rdm::RDMCommand::SET_COMMAND_RESPONSE, response->ParamId(), message.get()); else m_command_printer.DisplayResponse(response, true); }
/** * Display parameter data in hex and ascii */ void RDMSniffer::DisplayParamData(const PidDescriptor *pid_descriptor, bool is_get, const uint8_t *data, unsigned int length) { if (!length) return; cout << " Param data:" << endl; if (m_options.unpack_param_data && pid_descriptor) { const Descriptor *descriptor = is_get ? pid_descriptor->GetResponse() : pid_descriptor->SetResponse(); if (descriptor) { auto_ptr<const Message> message( m_pid_helper.DeserializeMessage(descriptor, data, length)); if (message.get()) { cout << m_pid_helper.MessageToString(message.get()); return; } } } // otherwise just display the raw data stringstream raw; raw << std::setw(2) << std::hex; stringstream ascii; for (unsigned int i = 0; i != length; i++) { raw << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(data[i]) << " "; if (data[i] >= ' ' && data[i] <= '~') ascii << data[i]; else ascii << "."; if (i % BYTES_PER_LINE == BYTES_PER_LINE - 1) { cout << " " << raw.str() << " " << ascii.str() << endl; raw.str(""); ascii.str(""); } } if (length % BYTES_PER_LINE != 0) { // pad if needed raw << string(3 * (BYTES_PER_LINE - (length % BYTES_PER_LINE)), ' '); cout << " " << raw.str() << " " << ascii.str() << endl; } }
/** * Display an RDM Request. */ void RDMSniffer::DisplayRDMRequest(unsigned int start, unsigned int end) { auto_ptr<RDMRequest> request( RDMRequest::InflateFromData(&m_frame[start], end - start + 1)); if (!request.get()) { DisplayRawData(start, end); return; } const PidDescriptor *descriptor = m_pid_helper.GetDescriptor( request->ParamId(), request->DestinationUID().ManufacturerId()); bool is_get = request->CommandClass() == RDMCommand::GET_COMMAND; if (m_options.summarize_rdm_frames) { cout << request->SourceUID() << " -> " << request->DestinationUID() << " " << (is_get ? "GET" : "SET") << ", sub-device: " << std::dec << request->SubDevice() << ", tn: " << static_cast<int>(request->TransactionNumber()) << ", port: " << std::dec << static_cast<int>(request->PortId()) << ", PID 0x" << std::hex << std::setfill('0') << std::setw(4) << request->ParamId(); if (descriptor) cout << " (" << descriptor->Name() << ")"; cout << ", pdl: " << std::dec << request->ParamDataSize() << endl; } else { cout << endl; cout << " Sub start code : 0x" << std::hex << static_cast<unsigned int>(m_frame[start]) << endl; cout << " Message length : " << static_cast<unsigned int>(m_frame[start + 1]) << endl; cout << " Dest UID : " << request->DestinationUID() << endl; cout << " Source UID : " << request->SourceUID() << endl; cout << " Transaction # : " << std::dec << static_cast<unsigned int>(request->TransactionNumber()) << endl; cout << " Port ID : " << std::dec << static_cast<unsigned int>(request->PortId()) << endl; cout << " Message count : " << std::dec << static_cast<unsigned int>(request->MessageCount()) << endl; cout << " Sub device : " << std::dec << request->SubDevice() << endl; cout << " Command class : " << (is_get ? "GET" : "SET") << endl; cout << " Param ID : 0x" << std::setfill('0') << std::setw(4) << std::hex << request->ParamId(); if (descriptor) cout << " (" << descriptor->Name() << ")"; cout << endl; cout << " Param data len : " << std::dec << request->ParamDataSize() << endl; DisplayParamData(descriptor, is_get, request->ParamData(), request->ParamDataSize()); } }
/** * Handle an ACK response */ void RDMController::HandleAckResponse(uint16_t manufacturer_id, bool is_set, uint16_t pid, const string &rdm_data) { const ola::rdm::PidDescriptor *pid_descriptor = m_pid_helper.GetDescriptor( pid, m_pending_request.uid->ManufacturerId()); if (!pid_descriptor) { OLA_WARN << "Unknown PID: " << pid << "."; return; } const ola::messaging::Descriptor *descriptor = NULL; if (is_set) descriptor = pid_descriptor->SetResponse(); else descriptor = pid_descriptor->GetResponse(); if (!descriptor) { OLA_WARN << "Unknown response message: " << (is_set ? "SET" : "GET") << " " << pid_descriptor->Name(); return; } auto_ptr<const ola::messaging::Message> message( m_pid_helper.DeserializeMessage( descriptor, reinterpret_cast<const uint8_t*>(rdm_data.data()), rdm_data.size())); if (!message.get()) { OLA_WARN << "Unable to inflate RDM response"; return; } cout << m_pid_helper.PrettyPrintMessage(manufacturer_id, is_set, pid, message.get()); }
/* * Dump the list of known pids */ void DisplayPIDsAndExit(uint16_t manufacturer_id, const PidStoreHelper &pid_helper) { vector<string> pid_names; pid_helper.SupportedPids(manufacturer_id, &pid_names); sort(pid_names.begin(), pid_names.end()); vector<string>::const_iterator iter = pid_names.begin(); for (; iter != pid_names.end(); ++iter) { cout << *iter << endl; } exit(ola::EXIT_OK); }
/** * Display an RDM response */ void RDMSniffer::DisplayRDMResponse(unsigned int start, unsigned int end) { ola::rdm::rdm_response_code code; unsigned int length = end - start + 1; auto_ptr<RDMResponse> response( RDMResponse::InflateFromData(&m_frame[start], length, &code)); if (!response.get()) { DisplayRawData(start, end); return; } const PidDescriptor *descriptor = m_pid_helper.GetDescriptor( response->ParamId(), response->SourceUID().ManufacturerId()); bool is_get = response->CommandClass() == RDMCommand::GET_COMMAND_RESPONSE; if (m_options.summarize_rdm_frames) { cout << response->SourceUID() << " -> " << response->DestinationUID() << " " << (is_get ? "GET_RESPONSE" : "SET_RESPONSE") << ", sub-device: " << std::dec << response->SubDevice() << ", tn: " << static_cast<int>(response->TransactionNumber()) << ", response type: "; switch (response->ResponseType()) { case ola::rdm::RDM_ACK: cout << "ACK"; break; case ola::rdm::RDM_ACK_TIMER: cout << "ACK TIMER"; break; case ola::rdm::RDM_NACK_REASON: if (length >= 26) { uint16_t reason; memcpy(reinterpret_cast<uint8_t*>(&reason), reinterpret_cast<const void*>(&m_frame[start + 23]), sizeof(reason)); reason = ola::network::NetworkToHost(reason); cout << "NACK (" << ola::rdm::NackReasonToString(reason) << ")"; } else { cout << "Malformed NACK "; } break; case ola::rdm::ACK_OVERFLOW: cout << "ACK OVERFLOW"; break; default: cout << "Unknown (" << response->ResponseType() << ")"; } cout << ", PID 0x" << std::hex << std::setfill('0') << std::setw(4) << response->ParamId(); if (descriptor) cout << " (" << descriptor->Name() << ")"; cout << ", pdl: " << std::dec << response->ParamDataSize() << endl; } else { cout << endl; cout << " Sub start code : 0x" << std::hex << static_cast<unsigned int>(m_frame[start]) << endl; cout << " Message length : " << static_cast<unsigned int>(m_frame[start + 1]) << endl; cout << " Dest UID : " << response->DestinationUID() << endl; cout << " Source UID : " << response->SourceUID() << endl; cout << " Transaction # : " << std::dec << static_cast<unsigned int>(response->TransactionNumber()) << endl; cout << " Response Type : "; switch (response->ResponseType()) { case ola::rdm::RDM_ACK: cout << "ACK"; break; case ola::rdm::RDM_ACK_TIMER: cout << "ACK TIMER"; break; case ola::rdm::RDM_NACK_REASON: if (length >= 26) { uint16_t reason; memcpy(reinterpret_cast<uint8_t*>(&reason), reinterpret_cast<const void*>(&m_frame[start + 23]), sizeof(reason)); reason = ola::network::NetworkToHost(reason); cout << "NACK (" << ola::rdm::NackReasonToString(reason) << ")"; } else { cout << "Malformed NACK "; } break; case ola::rdm::ACK_OVERFLOW: cout << "ACK OVERFLOW"; break; default: cout << "Unknown (" << response->ResponseType() << ")"; } cout << endl; cout << " Message count : " << std::dec << static_cast<unsigned int>(response->MessageCount()) << endl; cout << " Sub device : " << std::dec << response->SubDevice() << endl; cout << " Command class : " << (is_get ? "GET_RESPONSE" : "SET_RESPONSE") << endl; cout << " Param ID : 0x" << std::setfill('0') << std::setw(4) << std::hex << response->ParamId(); if (descriptor) cout << " (" << descriptor->Name() << ")"; cout << endl; cout << " Param data len : " << std::dec << response->ParamDataSize() << endl; DisplayParamData(descriptor, is_get, response->ParamData(), response->ParamDataSize()); } }
/** * Build a RDM Request from the options provided and send it to the daemon. */ int RDMController::PerformRequestAndWait(unsigned int universe, const UID &uid, uint16_t sub_device, const string &pid_name, bool is_set, const vector<string> &inputs) { // get the pid descriptor const ola::rdm::PidDescriptor *pid_descriptor = m_pid_helper.GetDescriptor( pid_name, uid.ManufacturerId()); uint16_t pid_value; if (!pid_descriptor && (ola::PrefixedHexStringToInt(pid_name, &pid_value) || ola::StringToInt(pid_name, &pid_value))) { pid_descriptor = m_pid_helper.GetDescriptor( pid_value, uid.ManufacturerId()); } if (!pid_descriptor) { cout << "Unknown PID: " << pid_name << endl; cout << "Use --list-pids to list the available PIDs." << endl; return ola::EXIT_USAGE; } const ola::messaging::Descriptor *descriptor = NULL; if (is_set) descriptor = pid_descriptor->SetRequest(); else descriptor = pid_descriptor->GetRequest(); if (!descriptor) { cout << (is_set ? "SET" : "GET") << " command not supported for " << pid_name << endl; exit(ola::EXIT_USAGE); } // attempt to build the message auto_ptr<const ola::messaging::Message> message(m_pid_helper.BuildMessage( descriptor, inputs)); if (!message.get()) { cout << m_pid_helper.SchemaAsString(descriptor); return ola::EXIT_USAGE; } m_pending_request.universe = universe; m_pending_request.uid = &uid; m_pending_request.sub_device = sub_device; m_pending_request.pid_value = pid_descriptor->Value(); unsigned int param_data_length; const uint8_t *param_data = m_pid_helper.SerializeMessage( message.get(), ¶m_data_length); if (is_set) { m_ola_client.GetClient()->RDMSet( ola::NewSingleCallback(this, &RDMController::HandleResponse), m_pending_request.universe, *m_pending_request.uid, m_pending_request.sub_device, pid_descriptor->Value(), param_data, param_data_length); } else { m_ola_client.GetClient()->RDMGet( ola::NewSingleCallback(this, &RDMController::HandleResponse), m_pending_request.universe, *m_pending_request.uid, m_pending_request.sub_device, pid_descriptor->Value(), param_data, param_data_length); } m_ola_client.GetSelectServer()->Run(); return ola::EXIT_OK; }
bool RDMController::InitPidHelper() { return m_pid_helper.Init(); }