How would I go about sending a simple insert command (or list of insert commands) through the Ignition S&F system in the Module SDK? I’m looking for something like the IA Labs “runSFPrepUpdate” Jython call.
That call is implemented via HistoryManager::storeHistory
, which you can get to from the GatewayContext
.
More info: that method expects a datasource name and a HistoricalData
object.
The simple implementation used by the scripting function looks like this:
public static class QuerySFData implements DatasourceData {
private static final long serialVersionUID = 1L;
String query;
String datasource;
Object[] values;
public QuerySFData(String query, String datasource) {
this(query, null, datasource);
}
public QuerySFData(String query, Object[] values, String datasource) {
this.query = query;
this.values = values;
this.datasource = datasource;
}
@Override
public int getDataCount() {
return 1;
}
@Override
public HistoryFlavor getFlavor() {
return DatasourceData.FLAVOR;
}
@Override
public String getLoggerName() {
return "Client Store & Forward";
}
@Override
public String getSignature() {
return "Scripted SF Query";
}
@Override
public void storeToConnection(SRConnection conn) throws Exception {
if (values != null) {
conn.runPrepUpdate(query, values);
} else {
conn.runUpdateQuery(query);
}
}
}
Awesome thanks!
Kevin,
Do you have and example of how to send alarm events through store and forward?
We’re pointing at Kafka and I can make tags work with/without S&F and alarms work w/o S&F but when trying to get alarms to go through S&F I’m struggling, I suspect because it’s expecting a different type than I’m providing.
Edited
Specifically I have a class Sink Data which implements HistoricalData like this:
public class SinkData implements HistoricalData {
private String topic, value, signature;
public SinkData(String topic, String value, String signature) {
this.topic = topic;
this.value = value;
this.signature = signature;
}
I put together the alarm data and call the function like this:
try {
String json = new JSONObject()
.put("type", "alarm")
.put("uuid", alarm.getId().toString())
.put("gatewayName", this.hostName)
.put("tagPath", src.replace("prov:", "[").replace(":/tag:", "]"))
.put("displayPath", path)
.put("priority", alarm.getPriority().ordinal())
.put("eventType", alarm.getState().ordinal())
.put("eventData", String.valueOf(data.getRawValueMap()))
.put("eventFlags", alarm.getLastEventState().ordinal())
.put("timestamp", data.getTimestamp())
.toString();
SinkData toSend = new SinkData(alarmTopic, json, alarmSignature);
sendKafkaData(toSend);
}
Finally it leads here where the call to storeHistory is made:
public int sendWithHistoryManager(String sinkName, SinkData data) throws Exception {
try {
this.historyManager.storeHistory(sinkName, data);
} catch (Exception e) {
logger.error("Error sending with history manager: " + e.getCause());
}
return 0;
}
The specific error I am trying to overcome is:
java.lang.ClassCastException: Cannot cast com.inductiveautomation.ignition.gateway.sqltags.model.BasicScanclassHistorySet to com.walmart.kafka.gateway.datasink.SinkData
Thanks,
Nick