From 10d6edad5ab722eb57fb7be5c16f201fad35a54c Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Fri, 17 Feb 2023 19:04:04 +0100 Subject: [PATCH] [DEV] add capability to get the data with the python timestamps --- back/pom.xml | 2 +- back/src/org/kar/karanage/WebLauncher.java | 1 + back/src/org/kar/karanage/api/Front.java | 2 +- .../src/org/kar/karanage/api/LogResource.java | 15 +++++- .../karanage/api/StateHistoryResource.java | 14 ++++- .../org/kar/karanage/api/StateResource.java | 50 +++++++++++++++-- .../bin/karanage-tools-state-get | 17 ++++-- client/python/karanage-tools/version.txt | 2 +- client/python/karanage/karanage/state.py | 53 +++++++++++++++---- client/python/karanage/version.txt | 2 +- 10 files changed, 132 insertions(+), 26 deletions(-) diff --git a/back/pom.xml b/back/pom.xml index cda3971..27a666a 100644 --- a/back/pom.xml +++ b/back/pom.xml @@ -22,7 +22,7 @@ kangaroo-and-rabbit archidata - 0.3.1 + 0.3.3 diff --git a/back/src/org/kar/karanage/WebLauncher.java b/back/src/org/kar/karanage/WebLauncher.java index 7915bfb..cf6ff6c 100755 --- a/back/src/org/kar/karanage/WebLauncher.java +++ b/back/src/org/kar/karanage/WebLauncher.java @@ -80,6 +80,7 @@ public class WebLauncher { rc.registerClasses(StateHistoryResource.class); rc.registerClasses(LogResource.class); + rc.registerClasses(HealthCheck.class); rc.registerClasses(Front.class); diff --git a/back/src/org/kar/karanage/api/Front.java b/back/src/org/kar/karanage/api/Front.java index 2fc76fe..59ede3d 100644 --- a/back/src/org/kar/karanage/api/Front.java +++ b/back/src/org/kar/karanage/api/Front.java @@ -13,7 +13,7 @@ import jakarta.ws.rs.core.Response.ResponseBuilder; import org.kar.archidata.api.FrontGeneric; import org.kar.karanage.util.ConfigVariable; -@Path("/karanage") +@Path("/front") public class Front extends FrontGeneric { public Front() { this.baseFrontFolder = ConfigVariable.getFrontFolder(); diff --git a/back/src/org/kar/karanage/api/LogResource.java b/back/src/org/kar/karanage/api/LogResource.java index a2c306a..3a30548 100644 --- a/back/src/org/kar/karanage/api/LogResource.java +++ b/back/src/org/kar/karanage/api/LogResource.java @@ -52,7 +52,8 @@ public class LogResource { @PathParam("system") String system, @QueryParam("since") String since, @QueryParam("sinceId") Integer sinceId, - @QueryParam("limit") Integer limit) throws Exception { + @QueryParam("limit") Integer limit, + @QueryParam("mode") String mode) throws Exception { // Keep Group ID: if (groupName == null || groupName.length() == 0) { throw new InputException("group", "Missing URL parameter /state/{group}/..."); @@ -136,7 +137,17 @@ public class LogResource { } else { out.append(","); } - out.append("{ \"id\": " + data.id + ", \"time\": \"" + data.create_date.toInstant().toString() + "\", \"data\":" + data.data + "}"); + out.append("{ \"id\": " + data.id + ", \"time\": "); + + if ("raw".equals(mode)) { + double seconds = data.create_date.toInstant().toEpochMilli() * 0.001; + out.append(seconds); + } else { + out.append("\""); + out.append(data.create_date.toInstant().toString()); + out.append("\""); + } + out.append(", \"data\":" + data.data + "}"); } out.append("]"); return out.toString(); diff --git a/back/src/org/kar/karanage/api/StateHistoryResource.java b/back/src/org/kar/karanage/api/StateHistoryResource.java index e94a935..aaf1069 100644 --- a/back/src/org/kar/karanage/api/StateHistoryResource.java +++ b/back/src/org/kar/karanage/api/StateHistoryResource.java @@ -33,7 +33,8 @@ public class StateHistoryResource { @PathParam("topic") String topic, @QueryParam("since") String since, @QueryParam("sinceId") Integer sinceId, - @QueryParam("limit") Integer limit) throws Exception { + @QueryParam("limit") Integer limit, + @QueryParam("mode") String mode) throws Exception { // Keep Group ID: if (groupName == null || groupName.length() == 0) { throw new InputException("group", "Missing URL parameter /state/{group}/..."); @@ -117,7 +118,16 @@ public class StateHistoryResource { } else { out.append(","); } - out.append("{ \"id\": " + data.id + ", \"time\": \"" + data.modify_date.toInstant().toString() + "\", \"data\":" + data.data + "}"); + out.append("{ \"id\": " + data.id + ", \"time\": "); + if ("raw".equals(mode)) { + double seconds = data.modify_date.toInstant().toEpochMilli() * 0.001; + out.append(seconds); + } else { + out.append("\""); + out.append(data.modify_date.toInstant().toString()); + out.append("\""); + } + out.append(", \"data\":" + data.data + "}"); } out.append("]"); return out.toString(); diff --git a/back/src/org/kar/karanage/api/StateResource.java b/back/src/org/kar/karanage/api/StateResource.java index 3f19a83..bd8e56b 100644 --- a/back/src/org/kar/karanage/api/StateResource.java +++ b/back/src/org/kar/karanage/api/StateResource.java @@ -33,7 +33,8 @@ public class StateResource { public static String getWithTopic( @PathParam("group") String groupName, @PathParam("topic") String topic, - @QueryParam("since") String since) throws Exception { + @QueryParam("since") String since, + @QueryParam("mode") String mode) throws Exception { if (groupName == null || groupName.length() == 0) { throw new InputException("group", "Missing URL parameter /state/{group}/..."); } @@ -74,7 +75,28 @@ public class StateResource { throw new FailException(Response.Status.NOT_FOUND, "Topic does not exist: '" + topic + "'"); } } - return "{ \"time\": \"" + data.modify_date.toInstant().toString() + "\", \"data\":" + data.data + "}"; + StringBuilder out = new StringBuilder("{ \"time\": "); + if ("raw".equals(mode)) { + double seconds = data.modify_date.toInstant().toEpochMilli() * 0.001; + out.append(seconds); + return "{ \"time\": " + seconds + ", \"data\":" + data.data + "}"; + } else { + out.append("\""); + out.append(data.modify_date.toInstant().toString()); + out.append("\""); + } + out.append(", \"state\":"); + if (data.state == null) { + out.append("null"); + } else { + out.append("\""); + out.append(data.state); + out.append("\""); + } + out.append(", \"data\":"); + out.append(data.data); + out.append("}"); + return out.toString(); } @GET @@ -83,7 +105,8 @@ public class StateResource { @PermitAll public String get( @PathParam("group") String groupName, - @QueryParam("since") String since) throws Exception { + @QueryParam("since") String since, + @QueryParam("mode") String mode) throws Exception { if (groupName == null || groupName.length() == 0) { throw new InputException("group", "Missing URL parameter /state/{group}/..."); } @@ -125,7 +148,24 @@ public class StateResource { } else { out.append(","); } - out.append("{ \"time\": \"" + data.modify_date.toInstant().toString() + "\", \"topic\": \"" + data.topic + "\", \"data\":" + data.data + "}"); + out.append("{ \"time\": "); + if ("raw".equals(mode)) { + double seconds = data.modify_date.toInstant().toEpochMilli() * 0.001; + out.append(seconds); + } else { + out.append("\""); + out.append(data.modify_date.toInstant().toString()); + out.append("\""); + } + out.append(", \"state\":"); + if (data.state == null) { + out.append("null"); + } else { + out.append("\""); + out.append(data.state); + out.append("\""); + } + out.append(", \"topic\": \"" + data.topic + "\", \"data\":" + data.data + "}"); } out.append("]"); return out.toString(); @@ -148,7 +188,7 @@ public class StateResource { public Response post( @PathParam("group") String groupName, @PathParam("topic") String topic, - @QueryParam("state") String state, + @QueryParam("state") String state, String dataToInsert) throws Exception { StateInstant previous = null; diff --git a/client/python/karanage-tools/bin/karanage-tools-state-get b/client/python/karanage-tools/bin/karanage-tools-state-get index a358270..e2e5088 100755 --- a/client/python/karanage-tools/bin/karanage-tools-state-get +++ b/client/python/karanage-tools/bin/karanage-tools-state-get @@ -5,6 +5,7 @@ import json from pathlib import Path import subprocess import time +from datetime import timezone from typing import Dict, List from karanage import ( @@ -21,6 +22,8 @@ if __name__ == '__main__': parser.add_argument("-C", "--connection", type=str, help="json configuration file") parser.add_argument("-t", "--topic", type=str, help="Topic of the message") parser.add_argument("-s", "--since", type=str, help="Iso date since the value time must be") + parser.add_argument("-w", "--watch", help="Display new states", action='store_true') + # This element are read from the connection file: parser.add_argument("-u", "--url", type=str, help="Base URL of the web service") @@ -39,6 +42,14 @@ if __name__ == '__main__': # create the rest interface of karanage stateInterface = KaranageState(connection) - data = stateInterface.gets(topic=args.topic, since=args.since) - print(f"Ret = {json.dumps(data, indent=4)}") - + # transform since in a datetime: + while True: + data = stateInterface.gets(topic=args.topic, since=args.since) + for elem in data: + print(f"{elem.topic} @ {elem.time.astimezone()} => {elem.state}"); + print(json.dumps(elem.data, indent=4)) + args.since = elem.time + if not args.watch: + break + else: + time.sleep(1) diff --git a/client/python/karanage-tools/version.txt b/client/python/karanage-tools/version.txt index 9974c4b..7defe1e 100644 --- a/client/python/karanage-tools/version.txt +++ b/client/python/karanage-tools/version.txt @@ -1 +1 @@ -0.5.0-dev \ No newline at end of file +0.6.0-dev \ No newline at end of file diff --git a/client/python/karanage/karanage/state.py b/client/python/karanage/karanage/state.py index 7e5f334..49cff47 100644 --- a/client/python/karanage/karanage/state.py +++ b/client/python/karanage/karanage/state.py @@ -9,8 +9,9 @@ ## import enum import json -from typing import Dict, Optional +from typing import Dict, Optional, Union, List, NamedTuple +from datetime import datetime, timezone import requests from .connection import KaranageConnectionInterface @@ -22,6 +23,21 @@ class StateSystem(enum.Enum): FAIL = "FAIL" DOWN = "DOWN" +class StateData(NamedTuple): + topic: str + time: datetime + state: str + data: Dict + +def convert_to_state_data(json_data: Dict, topic:Optional[str] = None) -> StateData: + time = datetime.fromtimestamp(json_data["time"], timezone.utc) + if topic is not None: + topic = topic + else: + topic = json_data["topic"] + return StateData(topic, time, json_data["state"], json_data["data"]) + + ## Generic karanage sending system. class KaranageState: @@ -53,40 +69,57 @@ class KaranageState: f"Fail send message: '{ret.url}'", ret.status, ret.data ) - def gets(self, topic: Optional[str] = None, since: Optional[str] = None) -> Dict: + def gets(self, topic: Optional[str] = None, since: Union[None, str, datetime] = None) -> List[StateData]: """Get all the topic fom the server. :param since: ISO1866 time value. :return: A dictionary with the requested data. """ - param = {} + param = { + "mode":"raw" # request raw mode to have the timestant in a float in second + } if since is not None: - param["since"] = since + if since is str: + param["since"] = since + else: + param["since"] = since.replace(tzinfo=timezone.utc).isoformat() ret = self.connection.get("state", topic, params=param) if 200 <= ret.status <= 299: - return json.loads(ret.data) + out: List[StateData] = [] + for elem in json.loads(ret.data): + out.append(convert_to_state_data(elem, topic)) + return out raise KaranageException(f"Fail get data: '{ret.url}'", ret.status, ret.data) def get_history( self, topic: Optional[str] = None, - since: Optional[str] = None, + since: Union[None, str, datetime] = None, since_id: Optional[int] = None, limit: Optional[int] = None, - ) -> Dict: + ) -> List[StateData]: """Get all the topic fom the server. :param since: ISO1866 time value. :param since_id: remote BDD index of the field. :param limit: the number of value we want to get :return: A dictionary with the requested data. """ - param = {} + param = { + "mode":"raw" # request raw mode to have the timestant in a float in second + } if since is not None: - param["since"] = since + if since is str: + param["since"] = since + else: + param["since"] = since.replace(tzinfo=timezone.utc).isoformat() if since_id is not None: param["sinceId"] = since_id if limit is not None: param["limit"] = limit ret = self.connection.get("state_history", topic, params=param) if 200 <= ret.status <= 299: - return json.loads(ret.data) + out: List[StateData] = [] + for elem in json.loads(ret.data): + out.append(convert_to_state_data(elem, topic)) + return out + raise KaranageException(f"Fail get data: '{ret.url}'", ret.status, ret.data) diff --git a/client/python/karanage/version.txt b/client/python/karanage/version.txt index 9974c4b..7defe1e 100644 --- a/client/python/karanage/version.txt +++ b/client/python/karanage/version.txt @@ -1 +1 @@ -0.5.0-dev \ No newline at end of file +0.6.0-dev \ No newline at end of file