diff --git a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiDevice.java b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiDevice.java index 7159232..00e8b09 100644 --- a/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiDevice.java +++ b/src/src/main/java/com/my/graphiteDigesterBg/diframe/api/DiApiDevice.java @@ -4,10 +4,17 @@ import com.my.graphiteDigesterBg.diframe.model.DiMdbNotification; import jakarta.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseBody; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -19,6 +26,9 @@ public class DiApiDevice extends DiApiControllerBase { @Resource private DiDevice device; + @Value("${logging.file.name}") + private String logFileName; + /** * start device to execute tasks */ @@ -62,6 +72,15 @@ public class DiApiDevice extends DiApiControllerBase { } @ResponseBody + @PostMapping("/api/device/io-update") + public DiApiResponse ioUpdate( @RequestBody Map params ) { + String key = (String)params.get("key"); + Integer value = (Integer)params.get("value"); + this.device.getIO().setValue(key, value); + return this.success(); + } + + @ResponseBody @PostMapping("/api/device/actuator-list") public DiApiResponse actuatorList() { var list = this.device.getConfig().get("actuators"); @@ -69,6 +88,58 @@ public class DiApiDevice extends DiApiControllerBase { } @ResponseBody + @PostMapping("/api/device/actuator-execute-action") + public DiApiResponse actuatorExecuteAction( @RequestBody Map params ) { + String actuatorKey = (String)params.get("actuator"); + String actionName = (String)params.get("action"); + List actionParams = (List)params.get("params"); + + // setup action params + Class[] actionParamTypes = new Class[actionParams.size()]; + for (int i = 0; i < actionParams.size(); i++) { + var actionParam = actionParams.get(i); + if (actionParam instanceof Integer) { + actionParamTypes[i] = Integer.class; + } else if (actionParam instanceof String) { + actionParamTypes[i] = String.class; + } else if (actionParam instanceof Boolean) { + actionParamTypes[i] = Boolean.class; + } else { + throw new RuntimeException("Invalid action param type"); + } + } + + // setup action + DiActuator actuator = this.device.getActuators().get(actuatorKey); + if ( null == actuator ) { + return this.error("Invalid actuator key: " + actuatorKey); + } + + Method method = null; + try { + actionName = actionName.substring(0, 1).toLowerCase() + actionName.substring(1); + method = actuator.getClass().getMethod(actionName, actionParamTypes); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + + // execute action + Map result = new HashMap<>(); + result.put("result", null); + try { + if ( method.getReturnType().equals(Void.TYPE) ) { + method.invoke(actuator, actionParams.toArray()); + } else { + Object resultValue = method.invoke(actuator, actionParams.toArray()); + result.put("result", resultValue); + } + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + return this.success(result); + } + + @ResponseBody @PostMapping("/api/device/notification-fetch-one") public DiApiResponse notificationFetchOne() { var notification = DiActiveRecord.findOne(DiMdbNotification.class, Map.of("status", "new")); @@ -79,6 +150,40 @@ public class DiApiDevice extends DiApiControllerBase { return this.success(notification); } + @ResponseBody + @PostMapping("/api/device/app-log-fetch") + public DiApiResponse appLogFetch( @RequestBody Map params ) { + Integer offset = (Integer)params.get("offset"); + Integer limit = (Integer)params.get("limit"); + + // open log file and read limit from offset. + RandomAccessFile reader = null; + try { + reader = new RandomAccessFile(this.logFileName, "r"); + reader.seek(offset); + byte[] buffer = new byte[limit]; + int length = reader.read(buffer); + if ( -1 == length ) { + return this.success(Map.of("content", "", "length", 0)); + } + + String content = new String(buffer); + return this.success(Map.of("content", content, "length", length)); + } catch (FileNotFoundException e) { + return this.error("日志文件打开失败 : " + e.getMessage()); + } catch (IOException e) { + return this.error("日志文件读取失败 : " + e.getMessage()); + } finally { + if ( null != reader ) { + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + public void pause() {} public void resume() {} }