diff --git a/GenREADME.txt b/GenREADME.sh similarity index 95% rename from GenREADME.txt rename to GenREADME.sh index edc04517..75c1bf82 100644 --- a/GenREADME.txt +++ b/GenREADME.sh @@ -1,5 +1,5 @@ -for dir in */ -do - echo $dir - ( cd $dir && bash includeFile gen.md>README.md ) +for dir in */ +do + echo $dir + ( cd $dir && bash includeFile gen.md>README.md ) done \ No newline at end of file diff --git a/HTTPClient/README.md b/HTTPClient/README.md index 27904b73..84c5822d 100644 --- a/HTTPClient/README.md +++ b/HTTPClient/README.md @@ -13,33 +13,40 @@ Demo code: ```java -package com.ociweb.oe.floglight.api; +package com.ociweb.oe.greenlightning.api; -import com.ociweb.iot.maker.FogApp; -import com.ociweb.iot.maker.FogRuntime; -import com.ociweb.iot.maker.Hardware; +import com.ociweb.gl.api.Builder; +import com.ociweb.gl.api.GreenApp; +import com.ociweb.gl.api.GreenRuntime; +import com.ociweb.gl.api.HTTPSession; -public class HTTPClient implements FogApp +public class HTTPClient implements GreenApp { @Override - public void declareConnections(Hardware c) { + public void declareConfiguration(Builder c) { + //c.useInsecureNetClient(); c.useNetClient(); - c.enableTelemetry(); + } @Override - public void declareBehavior(FogRuntime runtime) { - - HTTPGetBehaviorSingle temp = new HTTPGetBehaviorSingle(runtime); - runtime.addStartupListener(temp); - + public void declareBehavior(GreenRuntime runtime) { - int responseId = runtime.addResponseListener(new HTTPResponse()).getId(); - runtime.addStartupListener(new HTTPGetBehaviorChained(runtime, responseId)); + HTTPSession session = new HTTPSession( + //"javanut.com",80,0); + "127.0.0.1",8088,0); + HTTPGetBehaviorSingle temp = new HTTPGetBehaviorSingle(runtime, session); + runtime.addStartupListener(temp).addSubscription("next"); + + //HTTPSession session = new HTTPSession("127.0.0.1",8088,0); + //runtime.addResponseListener(new HTTPResponse()).includeHTTPSession(session); + //runtime.addStartupListener(new HTTPGetBehaviorChained(runtime, session)); + + runtime.addPubSubListener(new ShutdownBehavior(runtime)).addSubscription("shutdown"); } @@ -49,26 +56,28 @@ public class HTTPClient implements FogApp Behavior class: ```java -package com.ociweb.oe.floglight.api; +package com.ociweb.oe.greenlightning.api; +import com.ociweb.gl.api.HTTPSession; import com.ociweb.gl.api.StartupListener; -import com.ociweb.iot.maker.FogCommandChannel; -import com.ociweb.iot.maker.FogRuntime; +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; public class HTTPGetBehaviorChained implements StartupListener { - private FogCommandChannel cmd; + private GreenCommandChannel cmd; private int responseId; - - public HTTPGetBehaviorChained(FogRuntime runtime, int responseId) { + private HTTPSession session; + + public HTTPGetBehaviorChained(GreenRuntime runtime, HTTPSession session) { this.cmd = runtime.newCommandChannel(NET_REQUESTER); - this.responseId = responseId; + this.session = session; } @Override public void startup() { - cmd.httpGet("www.objectcomputing.com", "/", responseId); + cmd.httpGet(session, "/testPageB"); } @@ -77,61 +86,98 @@ public class HTTPGetBehaviorChained implements StartupListener { ```java -package com.ociweb.oe.floglight.api; +package com.ociweb.oe.greenlightning.api; +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; import com.ociweb.gl.api.HTTPResponseListener; import com.ociweb.gl.api.HTTPResponseReader; +import com.ociweb.gl.api.HTTPSession; import com.ociweb.gl.api.Payloadable; +import com.ociweb.gl.api.PubSubListener; import com.ociweb.gl.api.StartupListener; -import com.ociweb.iot.maker.FogCommandChannel; -import com.ociweb.iot.maker.FogRuntime; -import com.ociweb.pronghorn.network.config.HTTPContentType; -import com.ociweb.pronghorn.pipe.BlobReader; +import com.ociweb.gl.api.TimeListener; +import com.ociweb.pronghorn.pipe.ChannelReader; +import com.ociweb.pronghorn.util.Appendables; -public class HTTPGetBehaviorSingle implements StartupListener, HTTPResponseListener { +public class HTTPGetBehaviorSingle implements StartupListener, HTTPResponseListener, PubSubListener { - private final FogCommandChannel cmd; - - public HTTPGetBehaviorSingle(FogRuntime runtime) { - cmd = runtime.newCommandChannel(NET_REQUESTER); + private final GreenCommandChannel cmd; + private HTTPSession session; + + public HTTPGetBehaviorSingle(GreenRuntime runtime, HTTPSession session) { + this.session = session; + cmd = runtime.newCommandChannel(NET_REQUESTER | DYNAMIC_MESSAGING); } + @Override public void startup() { - cmd.httpGet("www.objectcomputing.com", "/"); + cmd.publishTopic("next"); } + + long d = 0; + long c = 0; @Override public boolean responseHTTP(HTTPResponseReader reader) { - System.out.println(" status:"+reader.statusCode()); - System.out.println(" type:"+reader.contentType()); + long duration = System.nanoTime()-reqTime; + + d+=duration; + c+=1; + + if(0==(0xFFF&c)) {//running average + Appendables.appendNearestTimeUnit(System.err, d/c, " latency\n"); + } + + // System.out.println(" status:"+reader.statusCode()); + // System.out.println(" type:"+reader.contentType()); Payloadable payload = new Payloadable() { @Override - public void read(BlobReader reader) { - System.out.println(reader.readUTFOfLength(reader.available())); + public void read(ChannelReader reader) { + String readUTFOfLength = reader.readUTFOfLength(reader.available()); + //System.out.println(readUTFOfLength); } }; - + reader.openPayloadData( payload ); + cmd.publishTopic("next"); + return true; } + + int countDown = 4000; + long reqTime = 0; + + @Override + public boolean message(CharSequence topic, ChannelReader payload) { + + if (--countDown<=0) { + cmd.httpGet(session, "/shutdown?key=shutdown"); + cmd.publishTopic("shutdown"); + } + + reqTime = System.nanoTime(); + return cmd.httpGet(session, "/testPageB"); + + } + } ``` ```java -package com.ociweb.oe.floglight.api; +package com.ociweb.oe.greenlightning.api; import com.ociweb.gl.api.HTTPResponseListener; import com.ociweb.gl.api.HTTPResponseReader; import com.ociweb.gl.api.Payloadable; -import com.ociweb.pronghorn.network.config.HTTPContentType; -import com.ociweb.pronghorn.pipe.BlobReader; +import com.ociweb.pronghorn.pipe.ChannelReader; public class HTTPResponse implements HTTPResponseListener { @@ -143,7 +189,7 @@ public class HTTPResponse implements HTTPResponseListener { Payloadable payload = new Payloadable() { @Override - public void read(BlobReader reader) { + public void read(ChannelReader reader) { System.out.println(reader.readUTFOfLength(reader.available())); } }; @@ -157,4 +203,3 @@ public class HTTPResponse implements HTTPResponseListener { ``` -This class is a simple demonstration of an HTTP Client. HTTP Client will send a request out to an HTTP Server. In this case, the client is sending a request to go to "www.objectcomputing.com". \ No newline at end of file diff --git a/HTTPClient/gen.md b/HTTPClient/gen.md index 1b1a72fe..bfca2d73 100644 --- a/HTTPClient/gen.md +++ b/HTTPClient/gen.md @@ -11,10 +11,10 @@ # Example project: Demo code: -.include "./src/main/java/com/ociweb/oe/floglight/api/HTTPClient.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/HTTPClient.java" Behavior class: -.include "./src/main/java/com/ociweb/oe/floglight/api/HTTPGetBehaviorChained.java" -.include "./src/main/java/com/ociweb/oe/floglight/api/HTTPGetBehaviorSingle.java" -.include "./src/main/java/com/ociweb/oe/floglight/api/HTTPResponse.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/HTTPGetBehaviorChained.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/HTTPGetBehaviorSingle.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/HTTPResponse.java" This class is a simple demonstration of an HTTP Client. HTTP Client will send a request out to an HTTP Server. In this case, the client is sending a request to go to "www.objectcomputing.com". \ No newline at end of file diff --git a/HTTPServer/README.md b/HTTPServer/README.md index 6a0db01a..b748fc7a 100644 --- a/HTTPServer/README.md +++ b/HTTPServer/README.md @@ -13,54 +13,88 @@ Demo code: ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; -import com.ociweb.iot.maker.FogApp; -import com.ociweb.iot.maker.FogRuntime; -import com.ociweb.iot.maker.Hardware; +import com.ociweb.gl.api.Builder; +import com.ociweb.gl.api.GreenApp; +import com.ociweb.gl.api.GreenRuntime; import com.ociweb.pronghorn.network.config.HTTPHeaderDefaults; +import com.ociweb.pronghorn.util.AppendableProxy; +import com.ociweb.pronghorn.util.Appendables; -public class HTTPServer implements FogApp +public class HTTPServer implements GreenApp { - byte[] cookieHeader = HTTPHeaderDefaults.COOKIE.rootBytes(); + private byte[] cookieHeader = HTTPHeaderDefaults.COOKIE.rootBytes(); - int emptyResponseRouteId; - int smallResponseRouteId; - int largeResponseRouteId; - int fileServerId; + private int emptyResponseRouteId; + private int smallResponseRouteId; + private int largeResponseRouteId; + private int splitResponseRouteId; + private int shutdownRouteId; + + private AppendableProxy console; + private final String host; + private final int port; + public HTTPServer(String host, int port, Appendable console) { + this.host = host; + this.console = Appendables.proxy(console); + this.port = port; + } - byte[] myArgName = "myarg".getBytes(); + public HTTPServer(int port, Appendable console) { + this.host = null; + this.console = Appendables.proxy(console); + this.port = port; + } @Override - public void declareConnections(Hardware c) { + public void declareConfiguration(Builder c) { - c.enableServer(false, 8088); + c.useHTTP1xServer(port).setHost(host); + emptyResponseRouteId = c.registerRoute("/testpageA?arg=#{myarg}", cookieHeader); smallResponseRouteId = c.registerRoute("/testpageB"); largeResponseRouteId = c.registerRoute("/testpageC", cookieHeader); - fileServerId = c.registerRoute("/file${path}"); + splitResponseRouteId = c.registerRoute("/testpageD"); + + //only do in test mode... + //in production it is a bad idea to let clients turn off server. + shutdownRouteId = c.registerRoute("/shutdown?key=${key}"); + c.enableTelemetry(); } @Override - public void declareBehavior(FogRuntime runtime) { - runtime.addRestListener(new RestBehaviorEmptyResponse(runtime, myArgName)) + public void declareBehavior(GreenRuntime runtime) { + + runtime.addRestListener(new RestBehaviorEmptyResponse(runtime, "myarg", console)) .includeRoutes(emptyResponseRouteId); - runtime.addRestListener(new RestBehaviorSmallResponse(runtime)) + runtime.addRestListener(new RestBehaviorSmallResponse(runtime, console)) .includeRoutes(smallResponseRouteId); - runtime.addRestListener(new RestBehaviorLargeResponse(runtime)) + runtime.addRestListener(new RestBehaviorLargeResponse(runtime, console)) .includeRoutes(largeResponseRouteId); - //NOTE .includeAllRoutes() can be used to write a behavior taking all routes + runtime.addRestListener(new RestBehaviorHandoff(runtime, "responder")) + .includeRoutes(splitResponseRouteId); + + runtime.addPubSubListener(new RestBehaviorHandoffResponder(runtime, console)) + .addSubscription("responder"); - //NOTE when using the above no routes need to be registered and if they are - // all other routes will return a 404 + + + + //splitResponseRouteId + + runtime.addRestListener(new ShutdownRestListener(runtime)) + .includeRoutes(shutdownRouteId); + + //NOTE .includeAllRoutes() can be used to write a behavior taking all routes } @@ -70,60 +104,50 @@ public class HTTPServer implements FogApp Behavior class: ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; import com.ociweb.gl.api.HTTPRequestReader; -import com.ociweb.gl.api.Headable; -import com.ociweb.gl.api.Payloadable; import com.ociweb.gl.api.RestListener; -import com.ociweb.iot.maker.FogCommandChannel; -import com.ociweb.iot.maker.FogRuntime; import com.ociweb.pronghorn.network.config.HTTPHeaderDefaults; -import com.ociweb.pronghorn.pipe.BlobReader; +import com.ociweb.pronghorn.util.AppendableProxy; +import com.ociweb.pronghorn.util.Appendables; public class RestBehaviorEmptyResponse implements RestListener { - final byte[] cookieHeader = HTTPHeaderDefaults.COOKIE.rootBytes(); - final byte[] fieldName; - private final FogCommandChannel cmd; + private final int cookieHeader = HTTPHeaderDefaults.COOKIE.ordinal(); + private final byte[] fieldName; + private final GreenCommandChannel cmd; + private final AppendableProxy console; - public RestBehaviorEmptyResponse(FogRuntime runtime, byte[] myArgName) { - this.fieldName = myArgName; + public RestBehaviorEmptyResponse(GreenRuntime runtime, String myArgName, AppendableProxy console) { + this.fieldName = myArgName.getBytes(); this.cmd = runtime.newCommandChannel(NET_RESPONDER); + this.console = console; } - - Payloadable reader = new Payloadable() { - - @Override - public void read(BlobReader reader) { - - System.out.println("POST: "+reader.readUTFOfLength(reader.available())); - - } - }; - - private Headable headReader = new Headable() { - - @Override - public void read(BlobReader reader) { - - System.out.println("COOKIE: "+reader.readUTFOfLength(reader.available())); - - } - - }; - @Override public boolean restRequest(HTTPRequestReader request) { int argInt = request.getInt(fieldName); - System.out.println("Arg Int: "+argInt); - - request.openHeaderData(cookieHeader, headReader); + Appendables.appendValue(console, "Arg Int: ", argInt, "\n"); + + request.openHeaderData(cookieHeader, (id,reader)-> { + + console.append("COOKIE: "); + reader.readUTF(console).append('\n'); + + }); if (request.isVerbPost()) { - request.openPayloadData(reader ); + request.openPayloadData((reader)->{ + + console.append("POST: "); + reader.readUTFOfLength(reader.available(), console); + console.append('\n'); + + }); } //no body just a 200 ok response. @@ -136,70 +160,58 @@ public class RestBehaviorEmptyResponse implements RestListener { ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; import com.ociweb.gl.api.HTTPFieldReader; import com.ociweb.gl.api.HTTPRequestReader; -import com.ociweb.gl.api.NetResponseWriter; -import com.ociweb.gl.api.Writable; -import com.ociweb.gl.api.Payloadable; import com.ociweb.gl.api.RestListener; -import com.ociweb.iot.maker.FogCommandChannel; -import com.ociweb.iot.maker.FogRuntime; import com.ociweb.pronghorn.network.config.HTTPContentTypeDefaults; -import com.ociweb.pronghorn.pipe.BlobReader; -import com.ociweb.pronghorn.pipe.BlobWriter; +import com.ociweb.pronghorn.network.config.HTTPHeaderDefaults; +import com.ociweb.pronghorn.util.AppendableProxy; public class RestBehaviorLargeResponse implements RestListener { - private final FogCommandChannel cmd; + private final int cookieHeader = HTTPHeaderDefaults.COOKIE.ordinal(); + private final GreenCommandChannel cmd; private int partNeeded = 0; + private final AppendableProxy console; - public RestBehaviorLargeResponse(FogRuntime runtime) { + public RestBehaviorLargeResponse(GreenRuntime runtime, AppendableProxy console) { this.cmd = runtime.newCommandChannel(NET_RESPONDER); + this.console = console; } - Payloadable reader = new Payloadable() { - - @Override - public void read(BlobReader reader) { - - System.out.println("POST: "+reader.readUTFOfLength(reader.available())); - - } - }; - - - Writable writableA = new Writable() { - - @Override - public void write(BlobWriter writer) { - writer.writeUTF8Text("beginning of text file\n");//23 in length - } - - }; - - Writable writableB = new Writable() { - - @Override - public void write(BlobWriter writer) { - writer.writeUTF8Text("ending of text file\n");//20 in length - } - - }; - @Override public boolean restRequest(HTTPRequestReader request) { if (request.isVerbPost()) { - request.openPayloadData(reader); + request.openPayloadData((reader)->{ + + console.append("POST: "); + //TODO: why is this payload pointing to the cookie?? + //reader.readUTF(console); + reader.readUTFOfLength(reader.available(),console); + console.append('\n'); + + }); } + request.openHeaderData(cookieHeader, (id,reader)-> { + + console.append("COOKIE: "); + reader.readUTF(console).append('\n'); + + }); + if (0 == partNeeded) { boolean okA = cmd.publishHTTPResponse(request, 200, - request.getRequestContext(), + true, HTTPContentTypeDefaults.TXT, - writableA); + (writer)->{ + writer.writeUTF8Text("beginning of text file\n"); + }); if (!okA) { return false; } @@ -208,12 +220,14 @@ public class RestBehaviorLargeResponse implements RestListener { ////// //NB: this block is here for demo reasons however one could // publish a topic back to this behavior to complete the - // continuaton at a future time + // continuation at a future time ////// boolean okB = cmd.publishHTTPResponseContinuation(request, - request.getRequestContext() | HTTPFieldReader.END_OF_RESPONSE, - writableB); + false, + (writer)-> { + writer.writeUTF8Text("ending of text file\n"); + }); if (okB) { partNeeded = 0; return true; @@ -228,69 +242,45 @@ public class RestBehaviorLargeResponse implements RestListener { ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; import com.ociweb.gl.api.HTTPFieldReader; import com.ociweb.gl.api.HTTPRequestReader; -import com.ociweb.gl.api.NetResponseWriter; -import com.ociweb.gl.api.Writable; -import com.ociweb.gl.api.Payloadable; import com.ociweb.gl.api.RestListener; -import com.ociweb.iot.maker.FogCommandChannel; -import com.ociweb.iot.maker.FogRuntime; import com.ociweb.pronghorn.network.config.HTTPContentTypeDefaults; -import com.ociweb.pronghorn.pipe.BlobReader; -import com.ociweb.pronghorn.pipe.BlobWriter; +import com.ociweb.pronghorn.util.AppendableProxy; public class RestBehaviorSmallResponse implements RestListener { - private final FogCommandChannel cmd; + private final GreenCommandChannel cmd; + private final AppendableProxy console; - public RestBehaviorSmallResponse(FogRuntime runtime) { + public RestBehaviorSmallResponse(GreenRuntime runtime, AppendableProxy console) { this.cmd = runtime.newCommandChannel(NET_RESPONDER); + this.console = console; } - Payloadable reader = new Payloadable() { - - @Override - public void read(BlobReader reader) { - - System.out.println("POST: "+reader.readUTFOfLength(reader.available())); - - } - }; - - - Writable writableA = new Writable() { - - @Override - public void write(BlobWriter writer) { - writer.writeUTF8Text("beginning of text file\n"); - } - - }; - - Writable writableB = new Writable() { - - @Override - public void write(BlobWriter writer) { - writer.writeUTF8Text("this is some text\n"); - } - - }; - @Override public boolean restRequest(HTTPRequestReader request) { if (request.isVerbPost()) { - request.openPayloadData(reader ); + request.openPayloadData((reader)->{ + + console.append("POST: "); + reader.readUTFOfLength(reader.available(),console); + + }); } //if this can not be published then we will get the request again later to be reattempted. return cmd.publishHTTPResponse(request, 200, - request.getRequestContext() | HTTPFieldReader.END_OF_RESPONSE, + false, HTTPContentTypeDefaults.TXT, - writableA); + (writer)-> { + writer.writeUTF8Text("beginning of text file\n"); + }); } diff --git a/HTTPServer/gen.md b/HTTPServer/gen.md index d86079a8..e20a4ac6 100644 --- a/HTTPServer/gen.md +++ b/HTTPServer/gen.md @@ -11,9 +11,9 @@ # Example project: Demo code: -.include "./src/main/java/com/ociweb/oe/foglight/api/HTTPServer.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/HTTPServer.java" Behavior class: -.include "./src/main/java/com/ociweb/oe/foglight/api/RestBehaviorEmptyResponse.java" -.include "./src/main/java/com/ociweb/oe/foglight/api/RestBehaviorLargeResponse.java" -.include "./src/main/java/com/ociweb/oe/foglight/api/RestBehaviorSmallResponse.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/RestBehaviorEmptyResponse.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/RestBehaviorLargeResponse.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/RestBehaviorSmallResponse.java" This class is a simple demonstration of HTTPServer. HTTP Server will listen for an HTTP Client to send it a request. It will try to process the request, however, if it is unable to process it at that time, it will be reattempted later diff --git a/MQTTClient/README.md b/MQTTClient/README.md index 509fcf82..4cc08122 100644 --- a/MQTTClient/README.md +++ b/MQTTClient/README.md @@ -16,15 +16,201 @@ The following sketch will demonstrate a basic demo for using a MQTT. Demo code: -#### ERROR: could not read file ./src/main/java/com/ociweb/oe/foglight/api/MQTTClient.java + +```java +package com.ociweb.oe.greenlightning.api; + +import com.ociweb.gl.api.*; +import com.ociweb.oe.greenlightning.api.behaviors.EgressBehavior; +import com.ociweb.oe.greenlightning.api.behaviors.IngressBehavior; +import com.ociweb.oe.greenlightning.api.behaviors.TimeBehavior; +import com.ociweb.pronghorn.stage.scheduling.ScriptedNonThreadScheduler; + +public class MQTTClient implements GreenApp { + private MQTTBridge mqttConfig; + + //install mosquitto - replace 127.0.0.1 if using a different broker + // + //to monitor call > mosquitto_sub -v -t '#' -h 127.0.0.1 + //to test call > mosquitto_pub -h 127.0.0.1 -t 'external/topic/ingress' -m 'hello' + + @Override + public void declareConfiguration(Builder builder) { + + //TODO: the base is wrong for a script since they do not match total... + + ScriptedNonThreadScheduler.debug = false; + + //without low latency this PCT does not work.. + ScriptedNonThreadScheduler.lowLatencyEnforced = false; + + + //final String brokerHost = "127.0.0.1"; //1883 + //final String brokerHost = "172.16.10.28"; // Nathan's PC + //final String brokerHost = "thejoveexpress.local"; // Raspberry Pi0 + + final String brokerHost = "test.mosquitto.org"; + final int port = 1883;//8883; + + // Create a single mqtt client + mqttConfig = builder.useMQTT(brokerHost, port, "MQTTClientTest",200) //default of 10 in flight + + // .useTLS() + .cleanSession(true) + .keepAliveSeconds(10) + .lastWill("last/will", false, MQTTQoS.atLeastOnce, blobWriter -> {blobWriter.writeBoolean(true);}); + + // Timer rate + builder.setTimerPulseRate(1000); //once per second + + builder.enableTelemetry(8099); + } + + @Override + public void declareBehavior(final GreenRuntime runtime) { + // The external/internal topic translation is not necessary. + // The bridge calls may be made with one topic specified + final String internalEgressTopic = "internal/topic/egress"; + final String externalEgressTopic = "external/topic/egress"; + final String internalIngressTopic = "internal/topic/ingress"; + final String externalIngressTopic = "external/topic/ingress"; + final String localTestTopic = "localtest"; + + final MQTTQoS transQos = MQTTQoS.atLeastOnce; + final MQTTQoS subscribeQos = MQTTQoS.atLeastOnce; + + // Inject the timer that publishes topic/egress + TimeBehavior internalEgressTopicProducer = new TimeBehavior(runtime, internalEgressTopic); + runtime.addTimePulseListener(internalEgressTopicProducer); + // Convert the internal topic/egress to external for mqtt + runtime.bridgeTransmission(internalEgressTopic, externalEgressTopic, mqttConfig).setQoS(transQos); +; + // Subscribe to MQTT topic/ingress (created by mosquitto_pub example in comment above) + runtime.bridgeSubscription(internalIngressTopic, externalIngressTopic, mqttConfig).setQoS(subscribeQos); + // Listen to internal/topic/ingress and publish localtest + IngressBehavior mqttBrokerListener = new IngressBehavior(runtime, localTestTopic); + runtime.registerListener(mqttBrokerListener) + .addSubscription(internalIngressTopic, mqttBrokerListener::receiveMqttMessage); + + // Inject the listener for "localtest" + EgressBehavior doTheBusiness = new EgressBehavior(); + runtime.registerListener(doTheBusiness) + .addSubscription(localTestTopic, doTheBusiness::receiveTestTopic); + } +} +``` + Behavior class: -#### ERROR: could not read file ./src/main/java/com/ociweb/oe/foglight/api/TimeBehavior.java -#### ERROR: could not read file ./src/main/java/com/ociweb/oe/foglight/api/IngressBehavior.java +```java +package com.ociweb.oe.greenlightning.api.behaviors; + +import java.util.Date; + +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; +import com.ociweb.gl.api.TimeListener; +import com.ociweb.gl.api.WaitFor; +import com.ociweb.gl.api.Writable; + +public class TimeBehavior implements TimeListener { + private int droppedCount = 0; + private final GreenCommandChannel cmdChnl; + private final String publishTopic; + private long total = 0; + + public TimeBehavior(GreenRuntime runtime, String publishTopic) { + cmdChnl = runtime.newCommandChannel(DYNAMIC_MESSAGING); + this.publishTopic = publishTopic; + } + + @Override + public void timeEvent(long time, int iteration) { + int i = 1;//iterations + while (--i>=0) { + Date d = new Date(System.currentTimeMillis()); + + // On the timer event create a payload with a string encoded timestamp + Writable writable = writer -> writer.writeUTF8Text("'MQTT egress body " + d + "'"); + + // Send out the payload with thre MQTT topic "topic/egress" + boolean ok = cmdChnl.publishTopic(publishTopic, writable, WaitFor.None); + if (ok) { + System.err.println("sent "+d+" total "+(++total)); + } + else { + droppedCount++; + System.err.println("The system is backed up, dropped "+droppedCount); + } + } + } +} +``` + + + +```java +package com.ociweb.oe.greenlightning.api.behaviors; + +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; +import com.ociweb.gl.api.PubSubMethodListener; +import com.ociweb.gl.api.WaitFor; +import com.ociweb.gl.api.Writable; +import com.ociweb.pronghorn.pipe.ChannelReader; + +public class IngressBehavior implements PubSubMethodListener { + private final GreenCommandChannel cmd; + private final String publishTopic; + + public IngressBehavior(GreenRuntime runtime, String publishTopic) { + cmd = runtime.newCommandChannel(DYNAMIC_MESSAGING); + this.publishTopic = publishTopic; + } + + public boolean receiveMqttMessage(CharSequence topic, ChannelReader payload) { + // this received when mosquitto_pub is invoked - see MQTTClient + System.out.print("\ningress body: "); + + // Read the message payload and output it to System.out + payload.readUTFOfLength(payload.available(), System.out); + System.out.println(); + + // Create the on-demand mqtt payload writer + Writable mqttPayload = writer -> writer.writeUTF("\nsecond step test message"); + + // On the 'localtest' topic publish the mqtt payload + cmd.publishTopic(publishTopic, mqttPayload, WaitFor.None); + + // We consumed the message + return true; + } +} +``` + + + +```java +package com.ociweb.oe.greenlightning.api.behaviors; + +import com.ociweb.gl.api.PubSubMethodListener; +import com.ociweb.pronghorn.pipe.ChannelReader; + +public class EgressBehavior implements PubSubMethodListener { + + public boolean receiveTestTopic(CharSequence topic, ChannelReader payload) { + // topic is the MQTT topic + // payload is the MQTT payload + // this received when mosquitto_pub is invoked - see MQTTClient + System.out.println("got topic "+topic+" payload "+payload.readUTF()+"\n"); + + return true; + } +} +``` -#### ERROR: could not read file ./src/main/java/com/ociweb/oe/foglight/api/EgressBehavior.java This class is a simple demonstration of MQTT (Message Queue Telemetry Transport). A lightweight messaging protocal, it was inititially designed for constrained devices and low-bandwidth, high-latency or unreliable networks. This demo uses Mosquitto as a message broker, which means that the messages that are published will go through Mosquitto, which will send them to and subsrcibers of the topic. diff --git a/MQTTClient/gen.md b/MQTTClient/gen.md index 93e5960a..eb9f0247 100644 --- a/MQTTClient/gen.md +++ b/MQTTClient/gen.md @@ -16,15 +16,15 @@ The following sketch will demonstrate a basic demo for using a MQTT. Demo code: -.include "./src/main/java/com/ociweb/oe/foglight/api/MQTTClient.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/MQTTClient.java" Behavior class: -.include "./src/main/java/com/ociweb/oe/foglight/api/TimeBehavior.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/behaviors/TimeBehavior.java" -.include "./src/main/java/com/ociweb/oe/foglight/api/IngressBehavior.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/behaviors/IngressBehavior.java" -.include "./src/main/java/com/ociweb/oe/foglight/api/EgressBehavior.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/behaviors/EgressBehavior.java" This class is a simple demonstration of MQTT (Message Queue Telemetry Transport). A lightweight messaging protocal, it was inititially designed for constrained devices and low-bandwidth, high-latency or unreliable networks. This demo uses Mosquitto as a message broker, which means that the messages that are published will go through Mosquitto, which will send them to and subsrcibers of the topic. diff --git a/PubSub/README.md b/PubSub/README.md index 8abeae40..c0cce36c 100644 --- a/PubSub/README.md +++ b/PubSub/README.md @@ -16,33 +16,43 @@ Demo code: ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; -import com.ociweb.iot.maker.*; +import com.ociweb.gl.api.Builder; +import com.ociweb.gl.api.GreenApp; +import com.ociweb.gl.api.GreenRuntime; +import com.ociweb.pronghorn.util.AppendableProxy; +import com.ociweb.pronghorn.util.Appendables; -public class PubSub implements FogApp +public class PubSub implements GreenApp { - private final Appendable target; + private final AppendableProxy target; private final int seed; public PubSub(Appendable target, int seed) { - this.target = target; + this.target = Appendables.proxy(target); this.seed = seed; } @Override - public void declareConnections(Hardware c) { + public void declareConfiguration(Builder c) { //no connections are needed } - @Override - public void declareBehavior(FogRuntime runtime) { + public void declareBehavior(GreenRuntime runtime) { runtime.addStartupListener(new KickoffBehavior(runtime, target)); - runtime.addPubSubListener(new GenerateBehavior(runtime, "Count", target, seed)).addSubscription("Next"); - runtime.addPubSubListener(new CountBehavior(runtime, "Next")).addSubscription("Count"); + + runtime.addPubSubListener(new GenerateBehavior(runtime, "Count", target, seed)) + .addSubscription("Next"); + + CountBehavior counter = new CountBehavior(runtime, "Next"); + runtime.registerListener(counter) + .addSubscription("Count", counter::triggerNextAndCount) + .addSubscription("AnExample", counter::anotherMessage); + } diff --git a/PubSub/gen.md b/PubSub/gen.md index c88d2c54..3f6ae345 100644 --- a/PubSub/gen.md +++ b/PubSub/gen.md @@ -14,6 +14,6 @@ The following sketch will demonstrate a simple use of the ```addPubSubListener() Demo code: -.include "./src/main/java/com/ociweb/oe/foglight/api/PubSub.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/PubSub.java" The above code will generate seven random, lucky numbers. The first ```addPubSubListener()``` will generate a random number and add it to ArrayList ```luckyNums```. Once that has occured, it will publish a message uner the topic of "Gen", which the second PubSubListener is subscribed to, meaning that it is always listening for any publication under that topic. The second PubSubListener will simply print out the newest lucky number, then publish a message under the topic of "Print", which the first PubSubListener is subscribed to, restarting the process for a total of seven rounds. diff --git a/PubSubStructured/README.md b/PubSubStructured/README.md index 1b9cf4b9..3ffd2747 100644 --- a/PubSubStructured/README.md +++ b/PubSubStructured/README.md @@ -16,30 +16,50 @@ Demo code: ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; -import com.ociweb.iot.maker.FogApp; -import com.ociweb.iot.maker.FogRuntime; -import com.ociweb.iot.maker.Hardware; +import com.ociweb.gl.api.Builder; +import com.ociweb.gl.api.GreenApp; +import com.ociweb.gl.api.GreenRuntime; +import com.ociweb.pronghorn.util.AppendableProxy; +import com.ociweb.pronghorn.util.Appendables; -public class PubSubStructured implements FogApp +public class PubSubStructured implements GreenApp { - static int COUNT_DOWN_FIELD = 1; + static int VALUE_FIELD = 1; static int SENDER_FIELD = 2; - + + private AppendableProxy console; + private AppendableProxy console2; + + public PubSubStructured(Appendable console, Appendable console2) { + this.console = Appendables.proxy(console); + this.console2 = Appendables.proxy(console2); + } + @Override - public void declareConnections(Hardware c) { + public void declareConfiguration(Builder c) { } @Override - public void declareBehavior(FogRuntime runtime) { - // On startup kick off behavior will send the first message containing the first "topicOne" value - runtime.addStartupListener(new KickoffBehavior(runtime, "topicOne", 100)); - // DecrementValueBehavior 1 will process "topicOne" and send to "topicTwo" - runtime.addPubSubListener(new DecrementValueBehavior(runtime, "topicTwo", 1)).addSubscription("topicOne"); - // DecrementValueBehavior 2 will process "topicTwo" and send to "topicOne" - runtime.addPubSubListener(new DecrementValueBehavior(runtime, "topicOne", 1)).addSubscription("topicTwo"); - // The prcocess loop will end when value reaches 0 and a shutdown command is issued + public void declareBehavior(GreenRuntime runtime) { + + runtime.addStartupListener(new KickoffBehavior(runtime, "topicOne")); + + runtime.addPubSubListener(new IncrementValueBehavior(runtime, "topicTwo", console)) + .addSubscription("topicOne"); + + runtime.addPubSubListener(new IncrementValueBehavior(runtime, "topicOne", console)) + .addSubscription("topicTwo"); + + runtime.addPubSubListener(new FilterValueBehavior(runtime, "filteredValues")) + .addSubscription("topicOne") + .addSubscription("topicTwo"); + + runtime.addPubSubListener(new ConsoleWrite(console2)) + .addSubscription("filteredValues"); + + } } ``` @@ -49,21 +69,19 @@ Behavior class: ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; import com.ociweb.gl.api.StartupListener; -import com.ociweb.iot.maker.FogCommandChannel; -import com.ociweb.iot.maker.FogRuntime; public class KickoffBehavior implements StartupListener { - private final FogCommandChannel cmd; + private final GreenCommandChannel cmd; private final CharSequence publishTopic; - private final long countDownFrom; - KickoffBehavior(FogRuntime runtime, CharSequence publishTopic, long countDownFrom) { - cmd = runtime.newCommandChannel(DYNAMIC_MESSAGING); + KickoffBehavior(GreenRuntime runtime, CharSequence publishTopic) { + this.cmd = runtime.newCommandChannel(DYNAMIC_MESSAGING); this.publishTopic = publishTopic; - this.countDownFrom = countDownFrom; } @Override @@ -71,126 +89,50 @@ public class KickoffBehavior implements StartupListener { // Send the initial value on startup cmd.presumePublishStructuredTopic(publishTopic, writer -> { writer.writeUTF8(PubSubStructured.SENDER_FIELD, "from kickoff behavior"); - writer.writeLong(PubSubStructured.COUNT_DOWN_FIELD, countDownFrom); + writer.writeLong(PubSubStructured.VALUE_FIELD, 1); }); } } ``` - -```java -package com.ociweb.oe.foglight.api; - -import com.ociweb.gl.api.PubSubListener; -import com.ociweb.iot.maker.FogCommandChannel; -import com.ociweb.iot.maker.FogRuntime; -import com.ociweb.pronghorn.pipe.BlobReader; -import com.ociweb.pronghorn.util.field.MessageConsumer; - -public class DecrementValueBehavior implements PubSubListener { - private final FogCommandChannel channel; - private final MessageConsumer consumer; - private final CharSequence publishTopic; - private final FogRuntime runtime; - private final long decrementBy; - - private long lastValue; - - DecrementValueBehavior(FogRuntime runtime, CharSequence publishTopic, long decrementBy) { - this.channel = runtime.newCommandChannel(DYNAMIC_MESSAGING); - - // Process each field in order. Return false to stop processing. - this.consumer = new MessageConsumer() - .integerProcessor(PubSubStructured.COUNT_DOWN_FIELD, value -> { - lastValue = (int) value; - return true; - }); - - this.publishTopic = publishTopic; - this.runtime = runtime; - this.decrementBy = decrementBy; - } - - @Override - public boolean message(CharSequence topic, BlobReader payload) { - // - ////NOTE: this one line will copy messages from payload if consumer returns true - //// when the message is copied its topic is changed to the first argument string - // - //cmd.copyStructuredTopic(publishTopic, payload, consumer); - // - // consumer.process returns the process chain return value - if (consumer.process(payload)) { - if (lastValue>0) { - // If not zero, republish the message - System.out.println(lastValue); - return channel.publishStructuredTopic(publishTopic, writer -> { - writer.writeLong(PubSubStructured.COUNT_DOWN_FIELD, lastValue-decrementBy); - writer.writeUTF8(PubSubStructured.SENDER_FIELD, "from thing one behavior"); - }); - } else { - // When zero, shutdown the system - runtime.shutdownRuntime(); - return true; - } - } else { - return false; - } - } -} -``` - +#### ERROR: could not read file ./src/main/java/com/ociweb/oe/greenlightning/api/DecrementValueBehavior.java ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; import com.ociweb.gl.api.PubSubListener; -import com.ociweb.gl.api.PubSubStructuredWritable; -import com.ociweb.iot.maker.FogCommandChannel; -import com.ociweb.iot.maker.FogRuntime; -import com.ociweb.pronghorn.pipe.BlobReader; -import com.ociweb.pronghorn.util.field.IntegerFieldProcessor; +import com.ociweb.pronghorn.pipe.ChannelReader; import com.ociweb.pronghorn.util.field.MessageConsumer; -import com.ociweb.pronghorn.util.field.StructuredBlobWriter; public class ThingBehavior implements PubSubListener { - private final FogCommandChannel cmd; + private final GreenCommandChannel cmd; private final MessageConsumer consumer; private int lastValue; private final CharSequence publishTopic; - private final FogRuntime runtime; + private final GreenRuntime runtime; - public ThingBehavior(FogRuntime runtime, CharSequence topic) { + public ThingBehavior(GreenRuntime runtime, CharSequence topic) { this.cmd = runtime.newCommandChannel(DYNAMIC_MESSAGING); this.consumer = new MessageConsumer() - .integerProcessor(PubSubStructured.COUNT_DOWN_FIELD, processor); + .integerProcessor(PubSubStructured.VALUE_FIELD, + (value)->{ + lastValue = (int)value; + return true; + }); this.publishTopic = topic; this.runtime = runtime; } - private final PubSubStructuredWritable writable = new PubSubStructuredWritable() { - @Override - public void write(StructuredBlobWriter writer) { - writer.writeLong(PubSubStructured.COUNT_DOWN_FIELD, lastValue-1); - writer.writeUTF8(PubSubStructured.SENDER_FIELD, "from thing one behavior"); - } - }; - - private final IntegerFieldProcessor processor = new IntegerFieldProcessor() { - @Override - public boolean process(long value) { - lastValue = (int)value; - return true; - } - }; @Override - public boolean message(CharSequence topic, BlobReader payload) { + public boolean message(CharSequence topic, ChannelReader payload) { // ////NOTE: this one line will copy messages from payload if consumer returns true @@ -202,7 +144,10 @@ public class ThingBehavior implements PubSubListener { if (consumer.process(payload)) { if (lastValue>0) { System.out.println(lastValue); - return cmd.publishStructuredTopic(publishTopic, writable); + return cmd.publishStructuredTopic(publishTopic, (writer)->{ + writer.writeLong(PubSubStructured.VALUE_FIELD, lastValue-1); + writer.writeUTF8(PubSubStructured.SENDER_FIELD, "from thing one behavior"); + }); } else { runtime.shutdownRuntime(); return true; diff --git a/PubSubStructured/gen.md b/PubSubStructured/gen.md index 52e90205..35a1fcf6 100644 --- a/PubSubStructured/gen.md +++ b/PubSubStructured/gen.md @@ -14,15 +14,15 @@ The following sketch will demonstrate a basic demo for using a PubSub Structured Demo code: -.include "./src/main/java/com/ociweb/oe/foglight/api/PubSubStructured.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/PubSubStructured.java" Behavior class: -.include "./src/main/java/com/ociweb/oe/foglight/api/KickoffBehavior.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/KickoffBehavior.java" -.include "./src/main/java/com/ociweb/oe/foglight/api/DecrementValueBehavior.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/DecrementValueBehavior.java" -.include "./src/main/java/com/ociweb/oe/foglight/api/ThingBehavior.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/ThingBehavior.java" This class is a simple demonstration of PubSub Structured. While similar to the normal PubSub, PubSub Structured is meant for larger messages instead of just simpler ones. diff --git a/README.md b/README.md index c8316123..e20e0b85 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,92 @@ -# FogLight-API -API examples of oeFogLight features +# GreenLightning-API +API examples of oeGreenLightning features ## What It Is ## -FogLight is a Java 8 functional API for embedded systems that's built on top of [GreenLightning](https://github.com/oci-pronghorn/GreenLightning), a small footprint, garbage free compact 1 Java web server and message routing platform, +GreenLightning is a Java 8 functional API for embedded systems that's built on a small footprint, garbage free compact 1 Java web server and message routing platform, -FogLight is... +GreenLightning is... - Fast - Built on top of GreenLightning, FogLight is a garbage-free, lock-free and low latency way to talk directly to hardware. -- Simple - Taking advantage of the latest Java 8 APIs, FogLight has a clean and fluent set of APIs that make it easy to learn and apply with minimal training. -- Secure - By taking advantage of the compile-time graph validation system, all FogLight applications can be compiled and compressed to a point where injecting malicious code into the final production JAR would prove difficult, if not impossible. - -## How It Works ## -Every FogLight application starts with an `FogApp` implementation which initializes the `FogRuntime` by defining various hardware connections and behaviors for handling state changes in those connections. - -## What You Need Before You Start: -### Hardware -- [Raspberry Pi](https://www.raspberrypi.org/) -- [GrovePi+ Board](https://www.dexterindustries.com/shop/grovepi-board/) -### Software -- [Java 8](https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html) -- [Maven](https://maven.apache.org/install.html) -- [Git](https://git-scm.com/) -### Hardware Examples -- [Foglight-Grove](https://github.com/oci-pronghorn/FogLight-Grove/blob/master/README.md) -## Starting Your Maven Project -[Starting a mvn project](https://github.com/oci-pronghorn/FogLighter/blob/master/README.md) +- Simple - Taking advantage of the latest Java 8 APIs, GreenLightning has a clean and fluent set of APIs that make it easy to learn and apply with minimal training. +- Secure - By taking advantage of the compile-time graph validation system, all GreenLightning applications can be compiled and compressed to a point where injecting malicious code into the final production JAR would prove difficult, if not impossible. + +# GreenLightning +Fast small footprint HTTP server in Java + +This is early days for the project but we have enough here to prove out the core design. +Please consider sponsoring continued work on this BSD open source project. + +Drop a note to info@ociweb.com if you would like to set up a meeting to talk about Green Lightning. +What features are most important to you? + + +When running tests with a small 30 byte file I was able to to hit the following numbers +for unencrypted http calls on a 4 core box. + +The test makes 16K simultaneous (in flight) requests of 32 connections. Many more permutations are left to still be tested. + +Green Lightning: 1,000K RPS (saturated 1Gb connection) (in large mode) + +Green Lightning: 500K RPS (in small mode mode between 60-160MB of memory) + +NGINX: 260K RPS + +Netty: 160K RPS + + +The build server: +https://pronghorn.ci.cloudbees.com/job/GreenLightning/ + +The code on GitHub: +https://github.com/oci-pronghorn/GreenLightning + +To build a jar just run `mvn install` then run the `go.sh` +shell file to start up the demo web page +review `go.sh` to see how it is called. + +To build and run a native binary: + + 1. Download and install [Excelsior JET](https://www.excelsiorjet.com) + (the 90-day trial will work just fine). + 2. Do one of the following: + * Add the Excelsior JET `bin/` directory to `PATH` and run `mvn jet:build`. + * Run `mvn jet:build -Djet.home=`*JET-Home* + 3. Run `go-native.sh`. + +The zip file in `target/jet` can be copied to other systems. + +## Options + +--t is for turning on or off TLS (https) support, keys are built in cant change yet + +--s is the folder holding the static site pages, these can not be changed while its running + note if this points to the index.html file it will be used as the default for the domain. + +--l is for running in large mode where it allocates many GB for performance + with -l False (the small mode) it is still much more performant than any other + server I could find. + +--h what host to run this on (eg ip) if not provided it will guess from network settings. + +--p what port to run on the default is 8080 even when TLS is turned on. + + +When running small mode on a compact 1 JVM the app will only use about 60MB. +When running small mode on a normal JVM the app will use about 160MB. ## Information and Demos -- AnalogListener - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/AnalogListener/README.md) -- AnalogTransducer - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/AnalogTransducer/README.md) -- CommandChannel - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/CommandChannel/README.md) -- DeclareConnections - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/DeclareConnections/README.md) -- DigitalListener - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/DigitalListener/README.md) - HTTPClient - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/HTTPClient/README.md) + - [demo](https://github.com/oci-pronghorn/GreenLightning-API/blob/master/HTTPClient/README.md) - HTTPServer - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/HTTPServer/README.md) -- I2CListener - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/I2CListener/README.md) + - [demo](https://github.com/oci-pronghorn/GreenLightning-API/blob/master/HTTPServer/README.md) - MQTTClient - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/MQTTClient/README.md) + - [demo](https://github.com/oci-pronghorn/GreenLightning-API/blob/master/MQTTClient/README.md) - PubSub - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/PubSub/README.md) + - [demo](https://github.com/oci-pronghorn/GreenLightning-API/blob/master/PubSub/README.md) - PubSubStructured - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/PubSubStructured/README.md) -- SerialListener - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/SerialListener/README.md) + - [demo](https://github.com/oci-pronghorn/GreenLightning-API/blob/master/PubSubStructured/README.md) - Shutdown - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/Shutdown/README.md) + - [demo](https://github.com/oci-pronghorn/GreenLightning-API/blob/master/Shutdown/README.md) - Startup - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/Startup/README.md) + - [demo](https://github.com/oci-pronghorn/GreenLightning-API/tree/master/Startup) - StateMachine - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/StateMachine/README.md) + - [demo](https://github.com/oci-pronghorn/GreenLightning-API/tree/master/StateMachine) - Timer - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/Timer/README.md) -- Transducer - - [demo](https://github.com/oci-pronghorn/FogLight-API/blob/master/TransducerDemo/README.md) + - [demo](https://github.com/oci-pronghorn/GreenLightning-API/blob/master/Timer/README.md) diff --git a/Shutdown/README.md b/Shutdown/README.md index 13891b9d..f2be3d68 100644 --- a/Shutdown/README.md +++ b/Shutdown/README.md @@ -10,14 +10,105 @@ # Example project: -The following sketch will demonstrate a basic demo for using a ```I2CListener()```. +The following sketch will demonstrate a basic demo for using a ```Shutdown()```. Demo code: -#### ERROR: could not read file ./src/main/java/com/ociweb/oe/foglight/api/I2CListener.java + +```java +package com.ociweb.oe.greenlightning.api; + +import com.ociweb.gl.api.Builder; +import com.ociweb.gl.api.GreenApp; +import com.ociweb.gl.api.GreenRuntime; +import com.ociweb.gl.api.HTTPServerConfig; +import com.ociweb.pronghorn.network.NetGraphBuilder; + + +public class Shutdown implements GreenApp +{ + private final String host; + public Shutdown(String host) { + this.host = host; + } + + public Shutdown() { + this.host = null; + } + + @Override + public void declareConfiguration(Builder c) { + + HTTPServerConfig conf = c.useHTTP1xServer(8443) + .setHost(null==host?NetGraphBuilder.bindHost():host) + .setDefaultPath(""); + + c.defineRoute("/shutdown?key=${key}"); + } + + @Override + public void declareBehavior(final GreenRuntime runtime) { + runtime.registerListener(new ShutdownBehavior(runtime)).includeAllRoutes(); + } + +} +``` + Behavior class: -#### ERROR: could not read file ./src/main/java/com/ociweb/oe/foglight/api/I2CListenerBehavior.java -This class is a simple demonstration of how to use the ```I2CListener()```. This demonstration uses the I2C ADC, which is an analog to I2C converter. Also, take note that inside of the I2CListenerBehavior, there is also a startup listener which is necessary to begin an I2CListener. +```java +package com.ociweb.oe.greenlightning.api; + +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; +import com.ociweb.gl.api.HTTPRequestReader; +import com.ociweb.gl.api.RestListener; +import com.ociweb.gl.api.ShutdownListener; + +public class ShutdownBehavior implements ShutdownListener, RestListener{ + + private final GreenCommandChannel channel; + private final byte[] KEY = "key".getBytes(); + private final byte[] PASS1 = "2709843294721594".getBytes(); + private final byte[] PASS2 = "A5E8F4D8C1B987EFCC00A".getBytes(); + + private boolean hasFirstKey; + private boolean hasSecondKey; + + public ShutdownBehavior(GreenRuntime runtime) { + this.channel = runtime.newCommandChannel(NET_RESPONDER); + + } + + @Override + public boolean acceptShutdown() { + return hasFirstKey & hasSecondKey; + } + + @Override + public boolean restRequest(HTTPRequestReader request) { + + if (request.isEqual(KEY, PASS1)) { + if (channel.publishHTTPResponse(request, 200)) { + while(!channel.shutdown()){} + hasFirstKey = true; + return true; + } + } else if (hasFirstKey && request.isEqual(KEY, PASS2)) { + if (channel.publishHTTPResponse(request, 200)) { + hasSecondKey = true; + return true; + } + } else { + return channel.publishHTTPResponse(request, 404); + } + return false; + } + +} +``` + + +This class is a simple demonstration of how to use the ```Shutdown()```. This demonstration uses allows for shutdown of a device diff --git a/Shutdown/gen.md b/Shutdown/gen.md index f10e1b28..3b3e7294 100644 --- a/Shutdown/gen.md +++ b/Shutdown/gen.md @@ -10,14 +10,14 @@ # Example project: -The following sketch will demonstrate a basic demo for using a ```I2CListener()```. +The following sketch will demonstrate a basic demo for using a ```Shutdown()```. Demo code: -.include "./src/main/java/com/ociweb/oe/foglight/api/I2CListener.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/Shutdown.java" Behavior class: -.include "./src/main/java/com/ociweb/oe/foglight/api/I2CListenerBehavior.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/ShutdownBehavior.java" -This class is a simple demonstration of how to use the ```I2CListener()```. This demonstration uses the I2C ADC, which is an analog to I2C converter. Also, take note that inside of the I2CListenerBehavior, there is also a startup listener which is necessary to begin an I2CListener. +This class is a simple demonstration of how to use the ```Shutdown()```. This demonstration uses allows for shutdown of a device diff --git a/Startup/README.md b/Startup/README.md index 2396b13a..a46b868e 100644 --- a/Startup/README.md +++ b/Startup/README.md @@ -16,26 +16,40 @@ Demo code: ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; -import com.ociweb.iot.maker.FogApp; -import com.ociweb.iot.maker.FogRuntime; -import com.ociweb.iot.maker.Hardware; +import com.ociweb.gl.api.Builder; +import com.ociweb.gl.api.GreenApp; +import com.ociweb.gl.api.GreenRuntime; +import com.ociweb.pronghorn.util.AppendableProxy; +import com.ociweb.pronghorn.util.Appendables; -public class Startup implements FogApp +public class Startup implements GreenApp { + + private final AppendableProxy console; + + public Startup(Appendable console) { + this.console = Appendables.proxy(console); + } + + @Override - public void declareConnections(Hardware c) { - //No connections are needed + public void declareConfiguration(Builder c) { + } @Override - public void declareBehavior(FogRuntime runtime) { + public void declareBehavior(GreenRuntime runtime) { runtime.addStartupListener(()->{ - System.out.println("Hello, this message will display once at start"); + console.append("Hello, this message will display once at start\n"); + //now we shutdown the app + runtime.shutdownRuntime(); }); + + } } ``` diff --git a/Startup/gen.md b/Startup/gen.md index 5a10fb10..c15bf94a 100644 --- a/Startup/gen.md +++ b/Startup/gen.md @@ -14,7 +14,7 @@ The following sketch will demonstrate a simple use of the addStartupListener met Demo code: -.include "./src/main/java/com/ociweb/oe/foglight/api/Startup.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/Startup.java" When executed, the above code will send the string ```"Hello, this message will display once at start"`` as soon as the program begins running. NOTE: while it was not performed here, if a transducer uses a startup method, then the startup listener of the transducer will execute before the startup method in the behavior class. Also, if multiple transducers use startup a method, do not worry about an order, it will be done automatically. diff --git a/StateMachine/README.md b/StateMachine/README.md index de26e2d5..9a571a5e 100644 --- a/StateMachine/README.md +++ b/StateMachine/README.md @@ -17,30 +17,22 @@ Main Class ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; +import com.ociweb.gl.api.Builder; +import com.ociweb.gl.api.GreenApp; +import com.ociweb.gl.api.GreenRuntime; +import com.ociweb.pronghorn.util.AppendableProxy; +import com.ociweb.pronghorn.util.Appendables; -import static com.ociweb.iot.grove.GroveTwig.*; - -import com.ociweb.iot.maker.*; -import com.ociweb.oe.foglight.api.StateMachine.StopLight; - -import static com.ociweb.iot.maker.Port.*; - -import com.ociweb.gl.api.StateChangeListener; - -public class StateMachine implements FogApp +public class StateMachine implements GreenApp { - static String cGreen = "Green"; - static String cYellow = "Yellow"; - static String cRed = "Red"; - public enum StopLight{ - Go(cGreen), - Caution(cYellow), - Stop(cRed); + Go("Green"), + Caution("Yellow"), + Stop("Red"); private String color; @@ -52,23 +44,32 @@ public class StateMachine implements FogApp return color; } } - + + private final AppendableProxy console; + private final int rate; + + public StateMachine(Appendable console, int rate) { + this.console = Appendables.proxy(console); + this.rate = rate; + } @Override - public void declareConnections(Hardware c) { + public void declareConfiguration(Builder c) { c.startStateMachineWith(StopLight.Stop); - c.setTimerPulseRate(1); + c.setTimerPulseRate(rate); } - - @SuppressWarnings("unchecked") @Override - public void declareBehavior(FogRuntime runtime) { - + public void declareBehavior(GreenRuntime runtime) { - runtime.addTimePulseListener(new TimingBehavior(runtime)); - runtime.addStateChangeListener(new StateChangeBehavior()); + runtime.addTimePulseListener(new TimingBehavior(runtime, console)); + runtime.addStateChangeListener(new StateChangeBehavior(console)) + .includeStateChangeTo(StopLight.Go); + runtime.addStateChangeListener(new StateChangeBehavior(console)) + .includeStateChangeTo(StopLight.Stop); + + } } @@ -79,21 +80,26 @@ Behavior classes ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; import com.ociweb.gl.api.StateChangeListener; -import com.ociweb.iot.maker.FogCommandChannel; -import com.ociweb.iot.maker.FogRuntime; -import com.ociweb.oe.foglight.api.StateMachine.StopLight; +import com.ociweb.oe.greenlightning.api.StateMachine.StopLight; +import com.ociweb.pronghorn.util.AppendableProxy; -public class StateChangeBehavior implements StateChangeListener { +public class StateChangeBehavior implements StateChangeListener { + private final AppendableProxy console; + + public StateChangeBehavior(AppendableProxy console) { + this.console = console; + } @Override - public boolean stateChange(Enum oldState, Enum newState) { + public boolean stateChange(StopLight oldState, StopLight newState) { + + console.append(" It is time to ").append(newState.name()).append('\n'); - System.out.println("The light has chnaged to " + ((StopLight) newState).getColor()); - return true; + return true; //if we need to 'delay' the state change false can be returned. } } @@ -102,44 +108,54 @@ public class StateChangeBehavior implements StateChangeListener { ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; +import com.ociweb.gl.api.GreenCommandChannel; +import com.ociweb.gl.api.GreenRuntime; import com.ociweb.gl.api.TimeListener; -import com.ociweb.iot.maker.FogCommandChannel; -import com.ociweb.iot.maker.FogRuntime; -import com.ociweb.oe.foglight.api.StateMachine.StopLight; +import com.ociweb.oe.greenlightning.api.StateMachine.StopLight; +import com.ociweb.pronghorn.util.AppendableProxy; +import com.ociweb.pronghorn.util.Appendables; public class TimingBehavior implements TimeListener { - private static long startTime; - private static boolean haveStartTime = false; - private static final long fullTime = 15_000; //time from one red light to the next in milliseconds - final FogCommandChannel channel; - public TimingBehavior(FogRuntime runtime) { - channel = runtime.newCommandChannel(DYNAMIC_MESSAGING); + private static final long fullCycle = 20; //from one red light to the next in iterations + + private final GreenCommandChannel channel; + private final AppendableProxy console; + private final GreenRuntime runtime; + public TimingBehavior(GreenRuntime runtime, AppendableProxy console) { + this.channel = runtime.newCommandChannel(DYNAMIC_MESSAGING); + this.console = console; + this.runtime = runtime; } - @Override public void timeEvent(long time, int iteration) { - - if((time-startTime)%fullTime == 5_000) { - System.out.print("Go! "); - channel.changeStateTo(StopLight.Go); + + if(iteration%fullCycle == 0) { + changeState(time, StopLight.Go); } - else if((time-startTime)%fullTime == 10_000) { - System.out.print("Caution. "); - channel.changeStateTo(StopLight.Caution); + else if(iteration%fullCycle == 8) { + changeState(time, StopLight.Caution); } - else if((time-startTime)%fullTime == 0) { - System.out.print("Stop! "); - channel.changeStateTo(StopLight.Stop); + else if(iteration%fullCycle == 11) { + changeState(time, StopLight.Stop); } - if(!haveStartTime) { - startTime = time; - haveStartTime = true; + if (iteration == (fullCycle*3)) { + runtime.shutdownRuntime(7); + } + + } + + private void changeState(long time, StopLight target) { + if (channel.changeStateTo(target)) { + console.append(target.getColor()).append(" "); + Appendables.appendEpochTime(console, time).append('\n'); + } else { + console.append("unable to send state change, to busy"); } } diff --git a/StateMachine/gen.md b/StateMachine/gen.md index cd57d5f1..d01cb2b4 100644 --- a/StateMachine/gen.md +++ b/StateMachine/gen.md @@ -15,13 +15,13 @@ The following sketch will demonstrate a simple use of the ```StateChangeListener Demo code: Main Class -.include "./src/main/java/com/ociweb/oe/foglight/api/StateMachine.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/StateMachine.java" Behavior classes -.include "./src/main/java/com/ociweb/oe/foglight/api/StateChangeBehavior.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/StateChangeBehavior.java" -.include "./src/main/java/com/ociweb/oe/foglight/api/TimingBehavior.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/TimingBehavior.java" diff --git a/Timer/README.md b/Timer/README.md index 302b867b..74dca40d 100644 --- a/Timer/README.md +++ b/Timer/README.md @@ -16,30 +16,30 @@ Demo code: ```java -package com.ociweb.oe.foglight.api; +package com.ociweb.oe.greenlightning.api; +import com.ociweb.gl.api.*; +import com.ociweb.pronghorn.util.AppendableProxy; +import com.ociweb.pronghorn.util.Appendables; -//import static com.ociweb.iot.grove.GroveTwig.*; - -import com.ociweb.iot.maker.*; -import static com.ociweb.iot.maker.Port.*; - -public class Timer implements FogApp +public class Timer implements GreenApp { + private final AppendableProxy console; + private final int rate; + + public Timer(Appendable console, int rate) { + this.console = Appendables.proxy(console); + this.rate = rate; + } - @Override - public void declareConnections(Hardware c) { - c.setTimerPulseRate(1); //the rate at which time is checked in milliseconds - + public void declareConfiguration(Builder config) { + config.setTimerPulseRate(rate); //the rate at which time is checked in milliseconds } @Override - public void declareBehavior(FogRuntime runtime) { - - runtime.addTimePulseListener(new firstTimeBehavior(runtime)); - //runtime.addTimeListener(new secondTimeBehavior(runtime)); - + public void declareBehavior(GreenRuntime runtime) { + runtime.addTimePulseListener(new TimeBehavior(runtime, console)); } } ``` diff --git a/Timer/gen.md b/Timer/gen.md index efcf09a8..836e1c3f 100644 --- a/Timer/gen.md +++ b/Timer/gen.md @@ -14,6 +14,6 @@ The following sketch will demonstrate two simple uses of the addTimeListener() m Demo code: -.include "./src/main/java/com/ociweb/oe/foglight/api/Timer.java" +.include "./src/main/java/com/ociweb/oe/greenlightning/api/Timer.java" The first demo in this code uses the addTimeListener() method to print out the string "clock" at the top of every minute, regardless of when the program was started. The second demo uses the addTimeListener() method to print out the string "clock" at an interval of one minute since the start of the program. You can change the interval length by changing timeInterval .