mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 03:39:49 +03:00
input fix for mixed configs & repeat flag, comments
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
-DMULTIVENT_DISABLE
|
-DMULTIVENT_DISABLE
|
||||||
#-DWiz5100
|
#-DWiz5100
|
||||||
-DARDUINO_OTA_MDNS_DISABLE
|
-DARDUINO_OTA_MDNS_DISABLE
|
||||||
-DMDNS_ENABLE
|
#-DMDNS_ENABLE
|
||||||
|
|
||||||
-DHSV_DISABLE
|
-DHSV_DISABLE
|
||||||
-DPWM_DISABLE
|
-DPWM_DISABLE
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ extern volatile int8_t configLocked;
|
|||||||
extern bool configLoaded;
|
extern bool configLoaded;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints the data contained in a CAN frame.
|
||||||
|
*
|
||||||
|
* @param frame Pointer to the datagram_t structure containing the CAN frame.
|
||||||
|
* @param len Length of the data to print.
|
||||||
|
*/
|
||||||
void printFrame(datagram_t * frame, uint8_t len ) {
|
void printFrame(datagram_t * frame, uint8_t len ) {
|
||||||
|
|
||||||
debugSerial.print(" Data:");
|
debugSerial.print(" Data:");
|
||||||
@@ -38,6 +44,12 @@ void printFrame(datagram_t * frame, uint8_t len ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends the uptime metric to the CAN bus.
|
||||||
|
*
|
||||||
|
* @param ut Uptime value to send.
|
||||||
|
* @return true if the message was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::upTime(uint32_t ut)
|
bool canDriver::upTime(uint32_t ut)
|
||||||
{
|
{
|
||||||
if (!controllerId) return false;
|
if (!controllerId) return false;
|
||||||
@@ -57,6 +69,12 @@ bool canDriver::upTime(uint32_t ut)
|
|||||||
return write (id.id, &packet, 4);
|
return write (id.id, &packet, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends the salt metric to the CAN bus.
|
||||||
|
*
|
||||||
|
* @param salt Salt value to send.
|
||||||
|
* @return true if the message was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::salt(uint32_t salt)
|
bool canDriver::salt(uint32_t salt)
|
||||||
{
|
{
|
||||||
if (!controllerId) return false;
|
if (!controllerId) return false;
|
||||||
@@ -77,6 +95,11 @@ bool canDriver::salt(uint32_t salt)
|
|||||||
return write (id.id, &packet, 4);
|
return write (id.id, &packet, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Looks up the MAC address and sends it over the CAN bus.
|
||||||
|
*
|
||||||
|
* @return true if the MAC address was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::lookupMAC()
|
bool canDriver::lookupMAC()
|
||||||
{
|
{
|
||||||
// return 0;
|
// return 0;
|
||||||
@@ -102,6 +125,14 @@ bool canDriver::lookupMAC()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Requests a frame from the specified device on the CAN bus.
|
||||||
|
*
|
||||||
|
* @param devId Device ID to request the frame from.
|
||||||
|
* @param _payloadType Type of payload to request.
|
||||||
|
* @param seqNo Sequence number for the request.
|
||||||
|
* @return true if the request was successful, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::requestFrame(uint8_t devId, payloadType _payloadType, uint16_t seqNo )
|
bool canDriver::requestFrame(uint8_t devId, payloadType _payloadType, uint16_t seqNo )
|
||||||
{
|
{
|
||||||
canid_t id;
|
canid_t id;
|
||||||
@@ -127,6 +158,12 @@ packet.metric1 =0;
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends the remote ID of a device identified by its MAC address.
|
||||||
|
*
|
||||||
|
* @param mac MAC address of the device.
|
||||||
|
* @return true if the remote ID was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::sendRemoteID(macAddress mac)
|
bool canDriver::sendRemoteID(macAddress mac)
|
||||||
{
|
{
|
||||||
canid_t id;
|
canid_t id;
|
||||||
@@ -154,6 +191,11 @@ return res;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the CAN driver and sets up the CAN bus.
|
||||||
|
*
|
||||||
|
* @return true if initialization was successful, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::begin()
|
bool canDriver::begin()
|
||||||
{
|
{
|
||||||
if (root)
|
if (root)
|
||||||
@@ -207,6 +249,11 @@ bool canDriver::begin()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a frame from the CAN bus.
|
||||||
|
*
|
||||||
|
* @return Length of the received frame, or -1 if no frame was received.
|
||||||
|
*/
|
||||||
int canDriver::readFrame()
|
int canDriver::readFrame()
|
||||||
{
|
{
|
||||||
if (!ready) return -1;
|
if (!ready) return -1;
|
||||||
@@ -284,6 +331,9 @@ int canDriver::readFrame()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Polls the CAN bus for incoming frames and processes them.
|
||||||
|
*/
|
||||||
void canDriver::Poll()
|
void canDriver::Poll()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -355,6 +405,15 @@ switch (state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processes a received CAN packet.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the CAN packet.
|
||||||
|
* @param packet Pointer to the received datagram_t structure.
|
||||||
|
* @param len Length of the received packet.
|
||||||
|
* @param rtr Indicates if the packet is a remote transmission request.
|
||||||
|
* @return true if the packet was processed successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::processPacket(canid_t id, datagram_t *packet, uint8_t len, bool rtr)
|
bool canDriver::processPacket(canid_t id, datagram_t *packet, uint8_t len, bool rtr)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -557,6 +616,11 @@ else //Requests
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the device ID of this CAN driver.
|
||||||
|
*
|
||||||
|
* @return The device ID, or 0 if not set.
|
||||||
|
*/
|
||||||
uint8_t canDriver::getMyId()
|
uint8_t canDriver::getMyId()
|
||||||
{
|
{
|
||||||
if (!canConfigObj) return 0;
|
if (!canConfigObj) return 0;
|
||||||
@@ -565,6 +629,12 @@ if (addrObj && (addrObj->type == aJson_Int)) return addrObj->valueint;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the configuration object for a device by its ID.
|
||||||
|
*
|
||||||
|
* @param devId Device ID to look up.
|
||||||
|
* @return Pointer to the configuration object, or NULL if not found.
|
||||||
|
*/
|
||||||
aJsonObject * canDriver::getConfbyID(uint8_t devId)
|
aJsonObject * canDriver::getConfbyID(uint8_t devId)
|
||||||
{
|
{
|
||||||
if (!canConfigObj) return NULL;
|
if (!canConfigObj) return NULL;
|
||||||
@@ -583,6 +653,13 @@ while (remoteConfObj)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finds a configuration object by device name.
|
||||||
|
*
|
||||||
|
* @param devName Name of the device to look for.
|
||||||
|
* @param devAddr Pointer to store the device address if found.
|
||||||
|
* @return Pointer to the configuration object, or NULL if not found.
|
||||||
|
*/
|
||||||
aJsonObject * canDriver::findConfbyName(char* devName, int * devAddr)
|
aJsonObject * canDriver::findConfbyName(char* devName, int * devAddr)
|
||||||
{
|
{
|
||||||
if (!canRemoteConfigObj || canRemoteConfigObj->type != aJson_Object || !devName ) return NULL;
|
if (!canRemoteConfigObj || canRemoteConfigObj->type != aJson_Object || !devName ) return NULL;
|
||||||
@@ -611,6 +688,13 @@ return NULL;
|
|||||||
#if not defined (NOIP)
|
#if not defined (NOIP)
|
||||||
extern PubSubClient mqttClient;
|
extern PubSubClient mqttClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subscribes to MQTT topics based on the CAN configuration.
|
||||||
|
*
|
||||||
|
* @param root Pointer to the root topic string.
|
||||||
|
* @param buflen Length of the buffer for the topic string.
|
||||||
|
* @return true if subscription was successful, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::subscribeTopics(char * root, size_t buflen)
|
bool canDriver::subscribeTopics(char * root, size_t buflen)
|
||||||
{
|
{
|
||||||
if (!root) return false;
|
if (!root) return false;
|
||||||
@@ -643,6 +727,12 @@ while (remoteConfObj)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the device ID associated with a given MAC address.
|
||||||
|
*
|
||||||
|
* @param mac MAC address to look up.
|
||||||
|
* @return The device ID, or 0 if not found.
|
||||||
|
*/
|
||||||
uint8_t canDriver::getIdByMac(macAddress mac)
|
uint8_t canDriver::getIdByMac(macAddress mac)
|
||||||
{
|
{
|
||||||
char macStr[19];
|
char macStr[19];
|
||||||
@@ -675,6 +765,14 @@ if (addrObj && (addrObj->type == aJson_Int))
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a message over the CAN bus.
|
||||||
|
*
|
||||||
|
* @param msg_id Identifier for the message.
|
||||||
|
* @param buf Pointer to the datagram_t structure containing the message data.
|
||||||
|
* @param size Size of the message data.
|
||||||
|
* @return true if the message was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
||||||
{ //
|
{ //
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
@@ -724,12 +822,28 @@ bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends the status of a specified item.
|
||||||
|
*
|
||||||
|
* @param itemNum Item number to send the status for.
|
||||||
|
* @param cmd Command structure containing the status information.
|
||||||
|
* @param subItem Sub-item identifier.
|
||||||
|
* @return true if the status was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::sendStatus(uint16_t itemNum, itemCmd cmd, int subItem)
|
bool canDriver::sendStatus(uint16_t itemNum, itemCmd cmd, int subItem)
|
||||||
{
|
{
|
||||||
if (!itemNum || !controllerId) return false;
|
if (!itemNum || !controllerId) return false;
|
||||||
return sendCommand(controllerId, itemNum, cmd, true, subItem);
|
return sendCommand(controllerId, itemNum, cmd, true, subItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a command to a specified CAN device.
|
||||||
|
*
|
||||||
|
* @param can Pointer to the configuration object for the device.
|
||||||
|
* @param cmd Command structure containing the command information.
|
||||||
|
* @param status Indicates if the command is a status update.
|
||||||
|
* @return true if the command was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::sendCommand(aJsonObject * can, itemCmd cmd, bool status)
|
bool canDriver::sendCommand(aJsonObject * can, itemCmd cmd, bool status)
|
||||||
{
|
{
|
||||||
if (can && (can->type == aJson_Array))
|
if (can && (can->type == aJson_Array))
|
||||||
@@ -766,6 +880,16 @@ bool canDriver::sendCommand(aJsonObject * can, itemCmd cmd, bool status)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends a command to a specified device by ID.
|
||||||
|
*
|
||||||
|
* @param devID Device ID to send the command to.
|
||||||
|
* @param itemID Item ID to send the command for.
|
||||||
|
* @param cmd Command structure containing the command information.
|
||||||
|
* @param status Indicates if the command is a status update.
|
||||||
|
* @param subItemID Sub-item identifier.
|
||||||
|
* @return true if the command was sent successfully, false otherwise.
|
||||||
|
*/
|
||||||
bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool status,int subItemID )
|
bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool status,int subItemID )
|
||||||
{
|
{
|
||||||
canid_t id;
|
canid_t id;
|
||||||
@@ -801,6 +925,13 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
////////////////////////////// Steream //////////////////////////
|
////////////////////////////// Steream //////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends data over the CAN stream.
|
||||||
|
*
|
||||||
|
* @param len Length of the data to send.
|
||||||
|
* @param _seqNo Sequence number for the data.
|
||||||
|
* @return 1 if the data was sent successfully, 0 otherwise.
|
||||||
|
*/
|
||||||
int canStream::send(uint8_t len, uint16_t _seqNo)
|
int canStream::send(uint8_t len, uint16_t _seqNo)
|
||||||
{
|
{
|
||||||
canid_t id;
|
canid_t id;
|
||||||
@@ -823,6 +954,11 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks the state of the CAN stream and processes any incoming data.
|
||||||
|
*
|
||||||
|
* @return -1 on error, or the number of bytes available for reading.
|
||||||
|
*/
|
||||||
int canStream::checkState()
|
int canStream::checkState()
|
||||||
{
|
{
|
||||||
bool res = false;
|
bool res = false;
|
||||||
@@ -918,6 +1054,11 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
|
|
||||||
|
|
||||||
// Stream methods
|
// Stream methods
|
||||||
|
/**
|
||||||
|
* @brief Checks how many bytes are available for reading from the CAN stream.
|
||||||
|
*
|
||||||
|
* @return Number of bytes available, or -1 on error.
|
||||||
|
*/
|
||||||
int canStream::available()
|
int canStream::available()
|
||||||
{
|
{
|
||||||
if (!driver) return -1;
|
if (!driver) return -1;
|
||||||
@@ -925,6 +1066,11 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
return avail;
|
return avail;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a byte from the CAN stream.
|
||||||
|
*
|
||||||
|
* @return The byte read, or -1 on error.
|
||||||
|
*/
|
||||||
int canStream::read()
|
int canStream::read()
|
||||||
{
|
{
|
||||||
if (!driver) return -1;
|
if (!driver) return -1;
|
||||||
@@ -939,6 +1085,11 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
else return -1;
|
else return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Peeks at the next byte in the CAN stream without removing it.
|
||||||
|
*
|
||||||
|
* @return The next byte, or -1 on error.
|
||||||
|
*/
|
||||||
int canStream::peek()
|
int canStream::peek()
|
||||||
{
|
{
|
||||||
if (!driver) return -1;
|
if (!driver) return -1;
|
||||||
@@ -954,6 +1105,12 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes a byte to the CAN stream.
|
||||||
|
*
|
||||||
|
* @param c The byte to write.
|
||||||
|
* @return The number of bytes written, or -1 on error.
|
||||||
|
*/
|
||||||
size_t canStream::write(uint8_t c)
|
size_t canStream::write(uint8_t c)
|
||||||
{
|
{
|
||||||
//if ((state != canState::StreamOpenedWrite) || (state != canState::waitingConfirm)) return -1;
|
//if ((state != canState::StreamOpenedWrite) || (state != canState::waitingConfirm)) return -1;
|
||||||
@@ -984,12 +1141,20 @@ bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool sta
|
|||||||
}
|
}
|
||||||
return 1; };
|
return 1; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flushes the CAN stream, sending any buffered data.
|
||||||
|
*/
|
||||||
void canStream::flush()
|
void canStream::flush()
|
||||||
{
|
{
|
||||||
send(writePos,seqNo);
|
send(writePos,seqNo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if the CAN stream is available for writing.
|
||||||
|
*
|
||||||
|
* @return 1 if available, 0 if waiting for confirmation.
|
||||||
|
*/
|
||||||
int canStream::availableForWrite()
|
int canStream::availableForWrite()
|
||||||
{
|
{
|
||||||
switch (state)
|
switch (state)
|
||||||
|
|||||||
@@ -681,9 +681,9 @@ debugSerial << F("IN:") << pin << F(" DHT22 type. T=") << temp << F("°C H=") <<
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Polling via timed interrupt with CHECK_INTERRUPT cause
|
|
||||||
bool Input::
|
bool Input::
|
||||||
changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState)
|
changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState, bool calledOnTimer)
|
||||||
{
|
{
|
||||||
if (!inputObj || !store) return false;
|
if (!inputObj || !store) return false;
|
||||||
|
|
||||||
@@ -782,22 +782,30 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
|
|||||||
cmd = aJson.getObjectItem(currentInputObject, "rpcmd3");
|
cmd = aJson.getObjectItem(currentInputObject, "rpcmd3");
|
||||||
toggle=store->toggle3;
|
toggle=store->toggle3;
|
||||||
break;
|
break;
|
||||||
|
case IS_NOP:
|
||||||
|
if (!calledOnTimer) break;
|
||||||
|
if (contactState)
|
||||||
|
cmd = aJson.getObjectItem(currentInputObject, "scmd");
|
||||||
|
else cmd = aJson.getObjectItem(currentInputObject, "rcmd");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cause != CHECK_INTERRUPT)
|
if (!calledOnTimer || newState == IS_NOP)
|
||||||
{
|
{
|
||||||
onContactChanged(contactState);
|
if (cause != CHECK_INTERRUPT)
|
||||||
store->delayedState=false;
|
{
|
||||||
}
|
onContactChanged(contactState);
|
||||||
else
|
store->delayedState=false;
|
||||||
{
|
}
|
||||||
store->delayedState=true;
|
else
|
||||||
store->lastValue = contactState;
|
{
|
||||||
store->reqState=newState;
|
store->delayedState=true;
|
||||||
|
store->lastValue = contactState;
|
||||||
|
store->reqState=newState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newState == IS_NOP) return true;
|
if ((newState == IS_NOP) && !calledOnTimer) return true;
|
||||||
|
|
||||||
aJsonObject *defaultItem = aJson.getObjectItem(currentInputObject, "item");
|
aJsonObject *defaultItem = aJson.getObjectItem(currentInputObject, "item");
|
||||||
aJsonObject *defaultEmit = aJson.getObjectItem(currentInputObject, "emit");
|
aJsonObject *defaultEmit = aJson.getObjectItem(currentInputObject, "emit");
|
||||||
@@ -807,7 +815,7 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
|
|||||||
|
|
||||||
if (!cmd && !defCmd.isCommand())
|
if (!cmd && !defCmd.isCommand())
|
||||||
{
|
{
|
||||||
store->state=newState;
|
if (newState !=IS_NOP) store->state=newState;
|
||||||
store->delayedState=false;
|
store->delayedState=false;
|
||||||
return true; //nothing to do
|
return true; //nothing to do
|
||||||
}
|
}
|
||||||
@@ -815,7 +823,7 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
|
|||||||
|
|
||||||
if (cause != CHECK_INTERRUPT)
|
if (cause != CHECK_INTERRUPT)
|
||||||
{
|
{
|
||||||
store->state=newState;
|
if (newState !=IS_NOP) store->state=newState;
|
||||||
store->delayedState=false;
|
store->delayedState=false;
|
||||||
checkInstructions(cmd);
|
checkInstructions(cmd);
|
||||||
executeCommand(cmd,toggle,defCmd,defaultItem,defaultEmit,defaultCan);
|
executeCommand(cmd,toggle,defCmd,defaultItem,defaultEmit,defaultCan);
|
||||||
@@ -824,7 +832,7 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Postpone actual execution
|
//Postpone actual execution
|
||||||
if (newState != store->state)
|
if ((newState != store->state) && (newState !=IS_NOP))
|
||||||
{
|
{
|
||||||
store->reqState=newState;
|
store->reqState=newState;
|
||||||
store->delayedState=true;
|
store->delayedState=true;
|
||||||
@@ -880,15 +888,15 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_PRESSED:
|
case IS_PRESSED:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
||||||
{
|
{
|
||||||
if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(currentInputObject, "rpcmd")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState);
|
if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(currentInputObject, "rpcmd")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState,true);
|
||||||
else changeState(IS_LONG, cause,currentInputObject,currentInputState);
|
else changeState(IS_LONG, cause,currentInputObject,currentInputState,true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG:
|
case IS_LONG:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT, cause,currentInputObject,currentInputState);
|
changeState(IS_REPEAT, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -896,7 +904,7 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_REPEAT:
|
case IS_REPEAT:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT, cause,currentInputObject,currentInputState);
|
changeState(IS_REPEAT, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -904,15 +912,15 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_PRESSED2:
|
case IS_PRESSED2:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
||||||
{
|
{
|
||||||
if (!aJson.getObjectItem(currentInputObject, "lcmd2") && !aJson.getObjectItem(currentInputObject, "rpcmd2")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState);
|
if (!aJson.getObjectItem(currentInputObject, "lcmd2") && !aJson.getObjectItem(currentInputObject, "rpcmd2")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState,true);
|
||||||
else changeState(IS_LONG2, cause,currentInputObject,currentInputState);
|
else changeState(IS_LONG2, cause,currentInputObject,currentInputState,true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG2:
|
case IS_LONG2:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT2, cause,currentInputObject,currentInputState);
|
changeState(IS_REPEAT2, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -920,7 +928,7 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_REPEAT2:
|
case IS_REPEAT2:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT2, cause,currentInputObject,currentInputState);
|
changeState(IS_REPEAT2, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -930,17 +938,17 @@ switch (store->state) //Timer based transitions
|
|||||||
{
|
{
|
||||||
if (!aJson.getObjectItem(currentInputObject, "lcmd3") && !aJson.getObjectItem(currentInputObject, "rpcmd3")) //No longpress handlers
|
if (!aJson.getObjectItem(currentInputObject, "lcmd3") && !aJson.getObjectItem(currentInputObject, "rpcmd3")) //No longpress handlers
|
||||||
{
|
{
|
||||||
if (aJson.getObjectItem(currentInputObject, "scmd3")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState); //was used
|
if (aJson.getObjectItem(currentInputObject, "scmd3")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState,true); //was used
|
||||||
else changeState(IS_PRESSED2, cause,currentInputObject,currentInputState); // completely empty trippleClick section - fallback to first click handler
|
else changeState(IS_PRESSED2, cause,currentInputObject,currentInputState,true); // completely empty trippleClick section - fallback to first click handler
|
||||||
}
|
}
|
||||||
else changeState(IS_LONG3, cause,currentInputObject,currentInputState);
|
else changeState(IS_LONG3, cause,currentInputObject,currentInputState,true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG3:
|
case IS_LONG3:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT3, cause,currentInputObject,currentInputState);
|
changeState(IS_REPEAT3, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -948,7 +956,7 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_REPEAT3:
|
case IS_REPEAT3:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT3, cause,currentInputObject,currentInputState);
|
changeState(IS_REPEAT3, cause,currentInputObject,currentInputState,true);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -958,7 +966,7 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_WAITPRESS:
|
case IS_WAITPRESS:
|
||||||
|
|
||||||
|
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause,currentInputObject,currentInputState);
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause,currentInputObject,currentInputState,true);
|
||||||
break;
|
break;
|
||||||
} //switch
|
} //switch
|
||||||
#ifdef ROTARYENCODER
|
#ifdef ROTARYENCODER
|
||||||
@@ -1028,7 +1036,7 @@ if (re)
|
|||||||
res = changeState(IS_PRESSED3, cause,currentInputObject,currentInputState);
|
res = changeState(IS_PRESSED3, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
res = changeState(IS_NOP, cause,currentInputObject,currentInputState);
|
res = changeState(IS_NOP, cause,currentInputObject,currentInputState,(currentInputState == store->lastValue));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1064,7 +1072,7 @@ if (re)
|
|||||||
res = changeState(IS_IDLE, cause,currentInputObject,currentInputState);
|
res = changeState(IS_IDLE, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
res = changeState(IS_NOP, cause,currentInputObject,currentInputState);
|
res = changeState(IS_NOP, cause,currentInputObject,currentInputState, (currentInputState == store->lastValue));
|
||||||
}
|
}
|
||||||
if (res) { //State changed or postponed
|
if (res) { //State changed or postponed
|
||||||
// store->logicState = currentInputState;
|
// store->logicState = currentInputState;
|
||||||
@@ -1186,13 +1194,14 @@ strncpy(addrstr,emit->valuestring,sizeof(addrstr));
|
|||||||
if (mqttClient.connected() && !ethernetIdleCount)
|
if (mqttClient.connected() && !ethernetIdleCount)
|
||||||
{
|
{
|
||||||
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
|
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
|
||||||
|
|
||||||
if (newValue) { //send set command
|
if (newValue) { //send set command
|
||||||
if (!scmd || scmd->type != aJson_String) mqttClient.publish(addrstr, "ON", true);
|
if (!scmd) {mqttClient.publish(addrstr, "ON", true); debugSerial<<F("Emit:")<<addrstr<< F("->") << "ON"<<endl;}
|
||||||
else if (strlen(scmd->valuestring))
|
else if ((scmd->type == aJson_String) && strlen(scmd->valuestring))
|
||||||
mqttClient.publish(addrstr, scmd->valuestring, true);
|
{mqttClient.publish(addrstr, scmd->valuestring, true);debugSerial<<F("Emit:")<<addrstr<< F("->") << scmd->valuestring<<endl;}
|
||||||
} else { //send reset command
|
} else { //send reset command
|
||||||
if (!rcmd || rcmd->type != aJson_String) mqttClient.publish(addrstr, "OFF", true);
|
if (!rcmd) {mqttClient.publish(addrstr, "OFF", true);debugSerial<<F("Emit:")<<addrstr<< F("->") << "OFF"<<endl;}
|
||||||
else if (strlen(rcmd->valuestring))mqttClient.publish(addrstr, rcmd->valuestring, true);
|
else if ((rcmd->type == aJson_String) && strlen(rcmd->valuestring)) {mqttClient.publish(addrstr, rcmd->valuestring, true);debugSerial<<F("Emit:")<<addrstr<< F("->") << rcmd->valuestring<<endl;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif //NOIP
|
#endif //NOIP
|
||||||
@@ -1203,12 +1212,12 @@ if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestri
|
|||||||
Item it(item->valuestring);
|
Item it(item->valuestring);
|
||||||
if (it.isValid()) {
|
if (it.isValid()) {
|
||||||
if (newValue) { //send set command
|
if (newValue) { //send set command
|
||||||
if (!scmd || scmd->type != aJson_String) it.Ctrl(itemCmd(ST_VOID,CMD_ON));
|
if (!scmd ) it.Ctrl(itemCmd(ST_VOID,CMD_ON));
|
||||||
else if (strlen(scmd->valuestring))
|
else if ((scmd->type == aJson_String) && strlen(scmd->valuestring))
|
||||||
it.Ctrl(scmd->valuestring);
|
it.Ctrl(scmd->valuestring);
|
||||||
} else { //send reset command
|
} else { //send reset command
|
||||||
if (!rcmd || rcmd->type != aJson_String) it.Ctrl(itemCmd(ST_VOID,CMD_OFF));
|
if (!rcmd ) it.Ctrl(itemCmd(ST_VOID,CMD_OFF));
|
||||||
else if (strlen(rcmd->valuestring))
|
else if ((rcmd->type == aJson_String) && strlen(rcmd->valuestring))
|
||||||
it.Ctrl(rcmd->valuestring);
|
it.Ctrl(rcmd->valuestring);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ protected:
|
|||||||
bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...);
|
bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...);
|
||||||
|
|
||||||
char* getIdxField();
|
char* getIdxField();
|
||||||
bool changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState);
|
bool changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState, bool calledOnTimer = false);
|
||||||
void setupRotaryEncoder();
|
void setupRotaryEncoder();
|
||||||
|
|
||||||
aJsonObject * getCurrentInput();
|
aJsonObject * getCurrentInput();
|
||||||
|
|||||||
@@ -60,8 +60,18 @@ const reg_t regSize_P[] PROGMEM =
|
|||||||
} ;
|
} ;
|
||||||
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
|
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Меняет порядок байтов в 16-битном числе.
|
||||||
|
* @param x Входное число.
|
||||||
|
* @return Число с изменённым порядком байтов.
|
||||||
|
*/
|
||||||
uint16_t swap (uint16_t x) {return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);}
|
uint16_t swap (uint16_t x) {return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Преобразует строку в тип регистра.
|
||||||
|
* @param str Строка с типом регистра.
|
||||||
|
* @return Код типа регистра.
|
||||||
|
*/
|
||||||
int str2regSize(char * str)
|
int str2regSize(char * str)
|
||||||
{
|
{
|
||||||
for(uint8_t i=0; i<regSizeNum && str;i++)
|
for(uint8_t i=0; i<regSizeNum && str;i++)
|
||||||
@@ -71,6 +81,12 @@ int str2regSize(char * str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO irs etc
|
//TODO irs etc
|
||||||
|
/**
|
||||||
|
* @brief Получает имя параметра по номеру регистра.
|
||||||
|
* @param parameters JSON-объект с параметрами.
|
||||||
|
* @param regnum Номер регистра.
|
||||||
|
* @return Имя параметра или NULL.
|
||||||
|
*/
|
||||||
char * getParamNameByReg(aJsonObject * parameters, int regnum)
|
char * getParamNameByReg(aJsonObject * parameters, int regnum)
|
||||||
{
|
{
|
||||||
if (!parameters) return NULL;
|
if (!parameters) return NULL;
|
||||||
@@ -89,6 +105,11 @@ char * getParamNameByReg(aJsonObject * parameters, int regnum)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Проверяет наличие действия в JSON-объекте.
|
||||||
|
* @param execObj JSON-объект.
|
||||||
|
* @return true, если действие найдено, иначе false.
|
||||||
|
*/
|
||||||
bool haveAction(aJsonObject * execObj)
|
bool haveAction(aJsonObject * execObj)
|
||||||
{
|
{
|
||||||
aJsonObject * j = execObj->child;
|
aJsonObject * j = execObj->child;
|
||||||
@@ -111,6 +132,10 @@ case aJson_Array:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Загружает и применяет конфигурацию Modbus.
|
||||||
|
* @return true, если конфигурация успешно загружена, иначе false.
|
||||||
|
*/
|
||||||
bool out_Modbus::getConfig()
|
bool out_Modbus::getConfig()
|
||||||
{
|
{
|
||||||
// Retrieve and store template values from global modbus settings
|
// Retrieve and store template values from global modbus settings
|
||||||
@@ -224,6 +249,11 @@ bool out_Modbus::getConfig()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Создаёт поле для хранения последнего измеренного значения по имени параметра.
|
||||||
|
* @param name Имя параметра.
|
||||||
|
* @return true, если успешно, иначе false.
|
||||||
|
*/
|
||||||
int out_Modbus::createLastMeasured(char * name)
|
int out_Modbus::createLastMeasured(char * name)
|
||||||
{
|
{
|
||||||
if (!name) return false;
|
if (!name) return false;
|
||||||
@@ -231,6 +261,11 @@ aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
|||||||
return createLastMeasured(aJson.getObjectItem(itemParametersObj,name));
|
return createLastMeasured(aJson.getObjectItem(itemParametersObj,name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Создаёт поле для хранения последнего измеренного значения по JSON-объекту.
|
||||||
|
* @param execObj JSON-объект параметра.
|
||||||
|
* @return true, если успешно, иначе false.
|
||||||
|
*/
|
||||||
int out_Modbus::createLastMeasured(aJsonObject * execObj)
|
int out_Modbus::createLastMeasured(aJsonObject * execObj)
|
||||||
{
|
{
|
||||||
if (!execObj) return false;
|
if (!execObj) return false;
|
||||||
@@ -255,6 +290,11 @@ int out_Modbus::createLastMeasured(aJsonObject * execObj)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получает объект последнего измеренного значения по имени параметра.
|
||||||
|
* @param name Имя параметра.
|
||||||
|
* @return JSON-объект или NULL.
|
||||||
|
*/
|
||||||
aJsonObject * out_Modbus::getLastMeasured(char * name)
|
aJsonObject * out_Modbus::getLastMeasured(char * name)
|
||||||
{
|
{
|
||||||
if (!name) return NULL;
|
if (!name) return NULL;
|
||||||
@@ -262,6 +302,11 @@ aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
|||||||
return getLastMeasured (aJson.getObjectItem(itemParametersObj,name));
|
return getLastMeasured (aJson.getObjectItem(itemParametersObj,name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получает объект последнего измеренного значения по JSON-объекту.
|
||||||
|
* @param execObj JSON-объект параметра.
|
||||||
|
* @return JSON-объект или NULL.
|
||||||
|
*/
|
||||||
aJsonObject * out_Modbus::getLastMeasured(aJsonObject * execObj)
|
aJsonObject * out_Modbus::getLastMeasured(aJsonObject * execObj)
|
||||||
{
|
{
|
||||||
if (!execObj) return NULL;
|
if (!execObj) return NULL;
|
||||||
@@ -271,6 +316,10 @@ if (lastMeasured && lastMeasured->type == aJson_Int) return lastMeasured;
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализирует канал Modbus и загружает конфигурацию.
|
||||||
|
* @return 1 при успехе, 0 при ошибке.
|
||||||
|
*/
|
||||||
int out_Modbus::Setup()
|
int out_Modbus::Setup()
|
||||||
{
|
{
|
||||||
abstractOut::Setup();
|
abstractOut::Setup();
|
||||||
@@ -295,6 +344,10 @@ else
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Останавливает работу канала Modbus и освобождает ресурсы.
|
||||||
|
* @return 1 при успехе.
|
||||||
|
*/
|
||||||
int out_Modbus::Stop()
|
int out_Modbus::Stop()
|
||||||
{
|
{
|
||||||
debugSerial.print("MBUS: De-Init ");
|
debugSerial.print("MBUS: De-Init ");
|
||||||
@@ -309,6 +362,13 @@ return 1;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Читает данные из Modbus-устройства.
|
||||||
|
* @param reg Номер регистра.
|
||||||
|
* @param regType Тип регистра.
|
||||||
|
* @param count Количество регистров.
|
||||||
|
* @return true, если чтение успешно, иначе false.
|
||||||
|
*/
|
||||||
bool readModbus(uint16_t reg, int regType, int count)
|
bool readModbus(uint16_t reg, int regType, int count)
|
||||||
{
|
{
|
||||||
uint8_t result;
|
uint8_t result;
|
||||||
@@ -336,6 +396,17 @@ return (result == node.ku8MBSuccess);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Находит и обрабатывает регистр Modbus, выполняет сопоставление и действия.
|
||||||
|
* @param registerNum Номер регистра.
|
||||||
|
* @param posInBuffer Позиция в буфере ответа.
|
||||||
|
* @param regType Тип регистра.
|
||||||
|
* @param registerFrom Начальный регистр диапазона.
|
||||||
|
* @param registerTo Конечный регистр диапазона.
|
||||||
|
* @param doExecution Выполнять ли действие.
|
||||||
|
* @param submitParam Флаг для подавления повторных действий.
|
||||||
|
* @return Команда itemCmd с результатом.
|
||||||
|
*/
|
||||||
itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uint8_t regType, uint16_t registerFrom, uint16_t registerTo, bool doExecution, bool * submitParam)
|
itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uint8_t regType, uint16_t registerFrom, uint16_t registerTo, bool doExecution, bool * submitParam)
|
||||||
{
|
{
|
||||||
aJsonObject * paramObj = store->parameters->child;
|
aJsonObject * paramObj = store->parameters->child;
|
||||||
@@ -627,7 +698,12 @@ return itemCmd();
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void out_Modbus::pollModbus(aJsonObject * reg, int regType)
|
/**
|
||||||
|
* @brief Опрос Modbus-устройства по списку регистров.
|
||||||
|
* @param reg JSON-объект с регистрами.
|
||||||
|
* @param regType Тип регистра.
|
||||||
|
*/
|
||||||
|
void out_Modbus::pollModbus(aJsonObject * reg, int regType)
|
||||||
{
|
{
|
||||||
if (!reg) return;
|
if (!reg) return;
|
||||||
reg=reg->child;
|
reg=reg->child;
|
||||||
@@ -665,6 +741,9 @@ return itemCmd();
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализирует линию связи Modbus.
|
||||||
|
*/
|
||||||
void out_Modbus::initLine()
|
void out_Modbus::initLine()
|
||||||
{
|
{
|
||||||
//store->serialParam=(USARTClass::USARTModes) SERIAL_8N1;
|
//store->serialParam=(USARTClass::USARTModes) SERIAL_8N1;
|
||||||
@@ -683,6 +762,12 @@ void out_Modbus::initLine()
|
|||||||
node.begin(item->getArg(0), modbusSerial);
|
node.begin(item->getArg(0), modbusSerial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Отправляет значение в Modbus-устройство.
|
||||||
|
* @param paramName Имя параметра.
|
||||||
|
* @param outValue JSON-объект с отправляемым значением.
|
||||||
|
* @return 0 при успехе, отрицательное значение при ошибке.
|
||||||
|
*/
|
||||||
int out_Modbus::sendModbus(char * paramName, aJsonObject * outValue)
|
int out_Modbus::sendModbus(char * paramName, aJsonObject * outValue)
|
||||||
{
|
{
|
||||||
if (!store) {errorSerial<<F(" internal send error - no store")<<endl; return -1;}
|
if (!store) {errorSerial<<F(" internal send error - no store")<<endl; return -1;}
|
||||||
@@ -819,6 +904,11 @@ if ((res ==0) && (outValue->type == aJson_Int) && lastMeasured && (lastMeasured-
|
|||||||
return ( res == 0);
|
return ( res == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Осуществляет опрос и отправку команд Modbus.
|
||||||
|
* @param cause Причина вызова (например, медленный опрос).
|
||||||
|
* @return Интервал следующего опроса.
|
||||||
|
*/
|
||||||
int out_Modbus::Poll(short cause)
|
int out_Modbus::Poll(short cause)
|
||||||
{
|
{
|
||||||
if (cause==POLLING_SLOW) return 0;
|
if (cause==POLLING_SLOW) return 0;
|
||||||
@@ -949,11 +1039,21 @@ if (store->pollingRegisters || store->pollingIrs || store->pollingCoils || store
|
|||||||
return store->pollingInterval;
|
return store->pollingInterval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Возвращает тип канала.
|
||||||
|
* @return CH_MBUS.
|
||||||
|
*/
|
||||||
int out_Modbus::getChanType()
|
int out_Modbus::getChanType()
|
||||||
{
|
{
|
||||||
return CH_MBUS;
|
return CH_MBUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Отправляет команду itemCmd в Modbus по шаблону параметра.
|
||||||
|
* @param templateParamObj JSON-объект шаблона параметра.
|
||||||
|
* @param cmd Команда itemCmd.
|
||||||
|
* @return 1 при успехе, 0 при ошибке.
|
||||||
|
*/
|
||||||
int out_Modbus::sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd)
|
int out_Modbus::sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd)
|
||||||
{
|
{
|
||||||
if (templateParamObj)
|
if (templateParamObj)
|
||||||
@@ -1050,6 +1150,14 @@ else return 0;
|
|||||||
// 2. custom textual subItem
|
// 2. custom textual subItem
|
||||||
// 3. non-standard numeric suffix Code equal param id
|
// 3. non-standard numeric suffix Code equal param id
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Унифицированное управление Modbus-каналом.
|
||||||
|
* @param cmd Команда itemCmd.
|
||||||
|
* @param subItem Имя подэлемента.
|
||||||
|
* @param toExecute Выполнять ли команду.
|
||||||
|
* @param authorized Авторизовано ли выполнение.
|
||||||
|
* @return Результат выполнения.
|
||||||
|
*/
|
||||||
int out_Modbus::Ctrl(itemCmd cmd, char* subItem, bool toExecute,bool authorized)
|
int out_Modbus::Ctrl(itemCmd cmd, char* subItem, bool toExecute,bool authorized)
|
||||||
{
|
{
|
||||||
if (!store) return -1;
|
if (!store) return -1;
|
||||||
|
|||||||
Reference in New Issue
Block a user