mirror of
https://github.com/jlengrand/therobottle.git
synced 2026-03-10 08:41:18 +00:00
Start from robottle with Helidon
This commit is contained in:
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
target/*
|
||||
59
.gitignore
vendored
Normal file
59
.gitignore
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
.DS_Store
|
||||
.idea/shelf
|
||||
/android.tests.dependencies
|
||||
/confluence/target
|
||||
/dependencies/repo
|
||||
/dist
|
||||
/local
|
||||
/gh-pages
|
||||
/ideaSDK
|
||||
/clionSDK
|
||||
/android-studio/sdk
|
||||
out/
|
||||
/tmp
|
||||
workspace.xml
|
||||
*.versionsBackup
|
||||
/idea/testData/debugger/tinyApp/classes*
|
||||
/jps-plugin/testData/kannotator
|
||||
/js/js.translator/testData/out/
|
||||
/js/js.translator/testData/out-min/
|
||||
.gradle/
|
||||
build/
|
||||
!**/src/**/build
|
||||
!**/test/**/build
|
||||
*.iml
|
||||
!**/testData/**/*.iml
|
||||
.idea/libraries/Gradle*.xml
|
||||
.idea/libraries/Maven*.xml
|
||||
.idea/artifacts/PILL_*.xml
|
||||
.idea/artifacts/KotlinPlugin.xml
|
||||
.idea/modules
|
||||
.idea/runConfigurations/JPS_*.xml
|
||||
.idea/runConfigurations/PILL_*.xml
|
||||
.idea/libraries
|
||||
.idea/modules.xml
|
||||
.idea/gradle.xml
|
||||
.idea/compiler.xml
|
||||
.idea/inspectionProfiles/profiles_settings.xml
|
||||
.idea/.name
|
||||
.idea/artifacts/dist_auto_*
|
||||
.idea/artifacts/dist.xml
|
||||
.idea/artifacts/ideaPlugin.xml
|
||||
.idea/artifacts/kotlinc.xml
|
||||
.idea/artifacts/kotlin_compiler_jar.xml
|
||||
.idea/artifacts/kotlin_plugin_jar.xml
|
||||
.idea/artifacts/kotlin_jps_plugin_jar.xml
|
||||
.idea/artifacts/kotlin_daemon_client_jar.xml
|
||||
.idea/artifacts/kotlin_imports_dumper_compiler_plugin_jar.xml
|
||||
.idea/artifacts/kotlin_main_kts_jar.xml
|
||||
.idea/artifacts/kotlin_compiler_client_embeddable_jar.xml
|
||||
.idea/artifacts/kotlin_reflect_jar.xml
|
||||
kotlin-ultimate/
|
||||
node_modules/
|
||||
.rpt2_cache/
|
||||
libraries/tools/kotlin-test-js-runner/lib/
|
||||
libraries/tools/kotlin-source-map-loader/lib/
|
||||
local.properties
|
||||
|
||||
*.o
|
||||
target
|
||||
19
.idea/$PRODUCT_WORKSPACE_FILE$
generated
Normal file
19
.idea/$PRODUCT_WORKSPACE_FILE$
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
<state key="ProjectJDKs.UI">
|
||||
<settings>
|
||||
<last-edited>1.8</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
</states>
|
||||
</component>
|
||||
</project>
|
||||
15
.idea/deployment.xml
generated
Normal file
15
.idea/deployment.xml
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PublishConfigData" autoUpload="Always" serverName="raspberry.local" autoUploadExternalChanges="true">
|
||||
<serverData>
|
||||
<paths name="raspberry.local">
|
||||
<serverdata>
|
||||
<mappings>
|
||||
<mapping deploy="/" local="$PROJECT_DIR$" web="/" />
|
||||
</mappings>
|
||||
</serverdata>
|
||||
</paths>
|
||||
</serverData>
|
||||
<option name="myAutoUpload" value="ALWAYS" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/encodings.xml
generated
Normal file
6
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
17
.idea/misc.xml
generated
Normal file
17
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ElmWorkspace">
|
||||
<elmProjects />
|
||||
<settings binDirPath="" />
|
||||
</component>
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/classes" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
15
.idea/webServers.xml
generated
Normal file
15
.idea/webServers.xml
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="WebServers">
|
||||
<option name="servers">
|
||||
<webServer id="d7eae866-388d-4485-8638-0714f981dbf8" name="raspberry.local" url="http://raspberrypi.local">
|
||||
<fileTransfer host="raspberrypi.local" port="22" rootFolder="/home/pi/projects/therobottle" accessType="SFTP">
|
||||
<advancedOptions>
|
||||
<advancedOptions dataProtectionLevel="Private" passiveMode="true" shareSSLContext="true" />
|
||||
</advancedOptions>
|
||||
<option name="port" value="22" />
|
||||
</fileTransfer>
|
||||
</webServer>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
44
Dockerfile
Normal file
44
Dockerfile
Normal file
@@ -0,0 +1,44 @@
|
||||
#
|
||||
# Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# 1st stage, build the app
|
||||
FROM maven:3.5.4-jdk-9 as build
|
||||
|
||||
WORKDIR /helidon
|
||||
|
||||
# Create a first layer to cache the "Maven World" in the local repository.
|
||||
# Incremental docker builds will always resume after that, unless you update
|
||||
# the pom
|
||||
ADD pom.xml .
|
||||
RUN mvn package -DskipTests
|
||||
|
||||
# Do the Maven build!
|
||||
# Incremental docker builds will resume here when you change sources
|
||||
ADD src src
|
||||
RUN mvn package -DskipTests
|
||||
RUN echo "done!"
|
||||
|
||||
# 2nd stage, build the runtime image
|
||||
FROM openjdk:8-jre-slim
|
||||
WORKDIR /helidon
|
||||
|
||||
# Copy the binary built in the 1st stage
|
||||
COPY --from=build /helidon/target/therobottle.jar ./
|
||||
COPY --from=build /helidon/target/libs ./libs
|
||||
|
||||
CMD ["java", "-jar", "therobottle.jar"]
|
||||
|
||||
EXPOSE 8080
|
||||
35
README.md
Normal file
35
README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Robottle
|
||||
|
||||
WIP: Don't expect any structure in there. As of now it's a collection of tryouts without particular shape
|
||||
|
||||
A raspberry based sensor to keep my wine cellar under control
|
||||
|
||||
## Hardware :
|
||||
|
||||
* Raspberry (starting with a Raspberry 1)
|
||||
* Maybe Piface
|
||||
* DHT11 4 pins
|
||||
|
||||
## Readings
|
||||
|
||||
|
||||
http://www.circuitbasics.com/how-to-set-up-the-dht11-humidity-sensor-on-the-raspberry-pi/
|
||||
http://sebi.io/general/2018/08/13/Developing-for-Raspberry-Pi.html
|
||||
https://medium.com/@menchukanton/setup-intellij-idea-for-remote-debugging-java-code-on-a-raspberry-pi-6e9df09dfb95
|
||||
http://wiringpi.com/download-and-install/
|
||||
|
||||
https://github.com/cory-johannsen/gradle-jni-example
|
||||
|
||||
## Author
|
||||
|
||||
[Julien Lengrand-Lambert](https://github.com/jlengrand)
|
||||
|
||||
|
||||
pi/robottle
|
||||
raspberrypi
|
||||
|
||||
ping raspberrypi.local
|
||||
|
||||
|
||||
http://hirt.se/blog/?p=1116
|
||||
https://github.com/fauna/faunadb-jvm/blob/master/docs/java.md
|
||||
68
README_helidon.md
Normal file
68
README_helidon.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Helidon Quickstart MP Example
|
||||
|
||||
This example implements a simple Hello World REST service using MicroProfile.
|
||||
|
||||
## Build and run
|
||||
|
||||
With JDK8+
|
||||
```bash
|
||||
mvn package
|
||||
java -jar target/therobottle.jar
|
||||
```
|
||||
|
||||
## Exercise the application
|
||||
|
||||
```
|
||||
curl -X GET http://localhost:8080/greet
|
||||
{"message":"Hello World!"}
|
||||
|
||||
curl -X GET http://localhost:8080/greet/Joe
|
||||
{"message":"Hello Joe!"}
|
||||
|
||||
curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Hola"}' http://localhost:8080/greet/greeting
|
||||
|
||||
curl -X GET http://localhost:8080/greet/Jose
|
||||
{"message":"Hola Jose!"}
|
||||
```
|
||||
|
||||
## Try health and metrics
|
||||
|
||||
```
|
||||
curl -s -X GET http://localhost:8080/health
|
||||
{"outcome":"UP",...
|
||||
. . .
|
||||
|
||||
# Prometheus Format
|
||||
curl -s -X GET http://localhost:8080/metrics
|
||||
# TYPE base:gc_g1_young_generation_count gauge
|
||||
. . .
|
||||
|
||||
# JSON Format
|
||||
curl -H 'Accept: application/json' -X GET http://localhost:8080/metrics
|
||||
{"base":...
|
||||
. . .
|
||||
|
||||
```
|
||||
|
||||
## Build the Docker Image
|
||||
|
||||
```
|
||||
docker build -t therobottle .
|
||||
```
|
||||
|
||||
## Start the application with Docker
|
||||
|
||||
```
|
||||
docker run --rm -p 8080:8080 therobottle:latest
|
||||
```
|
||||
|
||||
Exercise the application as described above
|
||||
|
||||
## Deploy the application to Kubernetes
|
||||
|
||||
```
|
||||
kubectl cluster-info # Verify which cluster
|
||||
kubectl get pods # Verify connectivity to cluster
|
||||
kubectl create -f app.yaml # Deploy application
|
||||
kubectl get service therobottle # Verify deployed service
|
||||
```
|
||||
50
app.yaml
Normal file
50
app.yaml
Normal file
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: therobottle
|
||||
labels:
|
||||
app: therobottle
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: therobottle
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
name: http
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: extensions/v1beta1
|
||||
metadata:
|
||||
name: therobottle
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: therobottle
|
||||
version: v1
|
||||
spec:
|
||||
containers:
|
||||
- name: therobottle
|
||||
image: therobottle
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
---
|
||||
87
pom.xml
Normal file
87
pom.xml
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.helidon.applications</groupId>
|
||||
<artifactId>helidon-mp</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<groupId>nl.lengrand</groupId>
|
||||
<artifactId>therobottle</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
|
||||
<properties>
|
||||
<mainClass>nl.lengrand.therobottle.Main</mainClass>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.helidon.microprofile.bundles</groupId>
|
||||
<artifactId>helidon-microprofile</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-json-binding</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss</groupId>
|
||||
<artifactId>jandex</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>javax.activation-api</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-libs</id>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jboss.jandex</groupId>
|
||||
<artifactId>jandex-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-index</id>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
29
src/main/c/Dht11Driver.c
Normal file
29
src/main/c/Dht11Driver.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <jni.h>
|
||||
#include "../java/nl/lengrand/therobottle/driver/nl_lengrand_therobottle_driver_Dht11Driver.h"
|
||||
#include "adafruit/Raspberry_Pi_2/pi_2_dht_read.h"
|
||||
|
||||
JNIEXPORT void JNICALL Java_Dht11Driver_sayHello(JNIEnv *env, jobject thisObj) {
|
||||
printf("Hello JNI!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
JNIEXPORT jfloatArray JNICALL Java_Dht11Driver_getTemperatureAndHumidity(JNIEnv *env, jobject thisObj){
|
||||
float humidity = 0, temperature = 0;
|
||||
int sensor = 11; // Make those dynamic one day?
|
||||
int pin = 4; // Make those dynamic one day?
|
||||
int res = pi_2_dht_read(sensor, pin, &humidity, &temperature); // Might wanna do something with status one day
|
||||
|
||||
jfloat* values = (jfloat *) malloc(2*sizeof(jfloat));
|
||||
values[0] = temperature;
|
||||
values[1] = humidity;
|
||||
|
||||
jfloatArray outJNIArray = (*env)->NewFloatArray(env, 2);
|
||||
if (NULL == outJNIArray) return NULL;
|
||||
|
||||
(*env)->SetFloatArrayRegion(env, outJNIArray, 0, 2, (const jfloat*)values);
|
||||
return outJNIArray;
|
||||
}
|
||||
26
src/main/c/Makefile
Normal file
26
src/main/c/Makefile
Normal file
@@ -0,0 +1,26 @@
|
||||
JAVA_HOME=/usr/lib/jvm/java-11-openjdk-armhf
|
||||
INCLUDES = -I. -I../java -Iadafruit/Raspberry_Pi_2 -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
|
||||
HEADERS = ../java/nl/lengrand/therobottle/driver/nl_lengrand_therobottle_driver_Dht11Driver.h adafruit/common_dht_read.h adafruit/Raspberry_Pi_2/pi_2_mmio.h adafruit/Raspberry_Pi_2/pi_2_dht_read.h
|
||||
FILES = adafruit/common_dht_read.c adafruit/Raspberry_Pi_2/pi_2_mmio.c adafruit/Raspberry_Pi_2/pi_2_dht_read.c Dht11Driver.c
|
||||
OUT = libdht11
|
||||
|
||||
default: all
|
||||
|
||||
all: clean compileJava library
|
||||
|
||||
program: Dht11Driver.c
|
||||
gcc -Wall $(INCLUDES) $(HEADERS) $(FILES) -o $(OUT)
|
||||
|
||||
library: Dht11Driver.c
|
||||
gcc -shared -fPIC -o $(OUT).so $(INCLUDES) $(FILES)
|
||||
|
||||
move:
|
||||
-cp $(OUT).so
|
||||
|
||||
compileJava:
|
||||
-cd ../java/nl/lengrand/therobottle/driver;javac -h . Dht11Driver.java;cd -;
|
||||
|
||||
clean:
|
||||
-rm ../java/nl/lengrand/therobottle/driver/nl_lengrand_therobottle_driver_Dht11Driver.h
|
||||
-rm -f $(OUT).so
|
||||
-rm -f $(OUT)
|
||||
1
src/main/c/README.md
Normal file
1
src/main/c/README.md
Normal file
@@ -0,0 +1 @@
|
||||
The code contained in the adafruit folder comes from https://github.com/adafruit/Adafruit_Python_DHT and will be used as driver
|
||||
158
src/main/c/adafruit/Raspberry_Pi_2/pi_2_dht_read.c
Normal file
158
src/main/c/adafruit/Raspberry_Pi_2/pi_2_dht_read.c
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright (c) 2014 Adafruit Industries
|
||||
// Author: Tony DiCola
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pi_2_dht_read.h"
|
||||
#include "pi_2_mmio.h"
|
||||
|
||||
// This is the only processor specific magic value, the maximum amount of time to
|
||||
// spin in a loop before bailing out and considering the read a timeout. This should
|
||||
// be a high value, but if you're running on a much faster platform than a Raspberry
|
||||
// Pi or Beaglebone Black then it might need to be increased.
|
||||
#define DHT_MAXCOUNT 32000
|
||||
|
||||
// Number of bit pulses to expect from the DHT. Note that this is 41 because
|
||||
// the first pulse is a constant 50 microsecond pulse, with 40 pulses to represent
|
||||
// the data afterwards.
|
||||
#define DHT_PULSES 41
|
||||
|
||||
int pi_2_dht_read(int type, int pin, float* humidity, float* temperature) {
|
||||
// Validate humidity and temperature arguments and set them to zero.
|
||||
if (humidity == NULL || temperature == NULL) {
|
||||
return DHT_ERROR_ARGUMENT;
|
||||
}
|
||||
*temperature = 0.0f;
|
||||
*humidity = 0.0f;
|
||||
|
||||
// Initialize GPIO library.
|
||||
if (pi_2_mmio_init() < 0) {
|
||||
return DHT_ERROR_GPIO;
|
||||
}
|
||||
|
||||
// Store the count that each DHT bit pulse is low and high.
|
||||
// Make sure array is initialized to start at zero.
|
||||
int pulseCounts[DHT_PULSES*2] = {0};
|
||||
|
||||
// Set pin to output.
|
||||
pi_2_mmio_set_output(pin);
|
||||
|
||||
// Bump up process priority and change scheduler to try to try to make process more 'real time'.
|
||||
set_max_priority();
|
||||
|
||||
// Set pin high for ~500 milliseconds.
|
||||
pi_2_mmio_set_high(pin);
|
||||
sleep_milliseconds(500);
|
||||
|
||||
// The next calls are timing critical and care should be taken
|
||||
// to ensure no unnecssary work is done below.
|
||||
|
||||
// Set pin low for ~20 milliseconds.
|
||||
pi_2_mmio_set_low(pin);
|
||||
busy_wait_milliseconds(20);
|
||||
|
||||
// Set pin at input.
|
||||
pi_2_mmio_set_input(pin);
|
||||
// Need a very short delay before reading pins or else value is sometimes still low.
|
||||
for (volatile int i = 0; i < 50; ++i) {
|
||||
}
|
||||
|
||||
// Wait for DHT to pull pin low.
|
||||
uint32_t count = 0;
|
||||
while (pi_2_mmio_input(pin)) {
|
||||
if (++count >= DHT_MAXCOUNT) {
|
||||
// Timeout waiting for response.
|
||||
set_default_priority();
|
||||
return DHT_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
// Record pulse widths for the expected result bits.
|
||||
for (int i=0; i < DHT_PULSES*2; i+=2) {
|
||||
// Count how long pin is low and store in pulseCounts[i]
|
||||
while (!pi_2_mmio_input(pin)) {
|
||||
if (++pulseCounts[i] >= DHT_MAXCOUNT) {
|
||||
// Timeout waiting for response.
|
||||
set_default_priority();
|
||||
return DHT_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
// Count how long pin is high and store in pulseCounts[i+1]
|
||||
while (pi_2_mmio_input(pin)) {
|
||||
if (++pulseCounts[i+1] >= DHT_MAXCOUNT) {
|
||||
// Timeout waiting for response.
|
||||
set_default_priority();
|
||||
return DHT_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Done with timing critical code, now interpret the results.
|
||||
|
||||
// Drop back to normal priority.
|
||||
set_default_priority();
|
||||
|
||||
// Compute the average low pulse width to use as a 50 microsecond reference threshold.
|
||||
// Ignore the first two readings because they are a constant 80 microsecond pulse.
|
||||
uint32_t threshold = 0;
|
||||
for (int i=2; i < DHT_PULSES*2; i+=2) {
|
||||
threshold += pulseCounts[i];
|
||||
}
|
||||
threshold /= DHT_PULSES-1;
|
||||
|
||||
// Interpret each high pulse as a 0 or 1 by comparing it to the 50us reference.
|
||||
// If the count is less than 50us it must be a ~28us 0 pulse, and if it's higher
|
||||
// then it must be a ~70us 1 pulse.
|
||||
uint8_t data[5] = {0};
|
||||
for (int i=3; i < DHT_PULSES*2; i+=2) {
|
||||
int index = (i-3)/16;
|
||||
data[index] <<= 1;
|
||||
if (pulseCounts[i] >= threshold) {
|
||||
// One bit for long pulse.
|
||||
data[index] |= 1;
|
||||
}
|
||||
// Else zero bit for short pulse.
|
||||
}
|
||||
|
||||
// Useful debug info:
|
||||
//printf("Data: 0x%x 0x%x 0x%x 0x%x 0x%x\n", data[0], data[1], data[2], data[3], data[4]);
|
||||
|
||||
// Verify checksum of received data.
|
||||
if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) {
|
||||
if (type == DHT11) {
|
||||
// Get humidity and temp for DHT11 sensor.
|
||||
*humidity = (float)data[0];
|
||||
*temperature = (float)data[2];
|
||||
}
|
||||
else if (type == DHT22) {
|
||||
// Calculate humidity and temp for DHT22 sensor.
|
||||
*humidity = (data[0] * 256 + data[1]) / 10.0f;
|
||||
*temperature = ((data[2] & 0x7F) * 256 + data[3]) / 10.0f;
|
||||
if (data[2] & 0x80) {
|
||||
*temperature *= -1.0f;
|
||||
}
|
||||
}
|
||||
return DHT_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return DHT_ERROR_CHECKSUM;
|
||||
}
|
||||
}
|
||||
32
src/main/c/adafruit/Raspberry_Pi_2/pi_2_dht_read.h
Normal file
32
src/main/c/adafruit/Raspberry_Pi_2/pi_2_dht_read.h
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2014 Adafruit Industries
|
||||
// Author: Tony DiCola
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#ifndef PI_2_DHT_READ_H
|
||||
#define PI_2_DHT_READ_H
|
||||
|
||||
#include "../common_dht_read.h"
|
||||
|
||||
// Read DHT sensor connected to GPIO pin (using BCM numbering). Humidity and temperature will be
|
||||
// returned in the provided parameters. If a successfull reading could be made a value of 0
|
||||
// (DHT_SUCCESS) will be returned. If there was an error reading the sensor a negative value will
|
||||
// be returned. Some errors can be ignored and retried, specifically DHT_ERROR_TIMEOUT or DHT_ERROR_CHECKSUM.
|
||||
int pi_2_dht_read(int sensor, int pin, float* humidity, float* temperature);
|
||||
|
||||
#endif
|
||||
71
src/main/c/adafruit/Raspberry_Pi_2/pi_2_mmio.c
Normal file
71
src/main/c/adafruit/Raspberry_Pi_2/pi_2_mmio.c
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2014 Adafruit Industries
|
||||
// Author: Tony DiCola
|
||||
// Based on code from Gert van Loo & Dom: http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pi_2_mmio.h"
|
||||
|
||||
#define GPIO_BASE_OFFSET 0x200000
|
||||
#define GPIO_LENGTH 4096
|
||||
|
||||
volatile uint32_t* pi_2_mmio_gpio = NULL;
|
||||
|
||||
int pi_2_mmio_init(void) {
|
||||
if (pi_2_mmio_gpio == NULL) {
|
||||
// Check for GPIO and peripheral addresses from device tree.
|
||||
// Adapted from code in the RPi.GPIO library at:
|
||||
// http://sourceforge.net/p/raspberry-gpio-python/
|
||||
FILE *fp = fopen("/proc/device-tree/soc/ranges", "rb");
|
||||
if (fp == NULL) {
|
||||
return MMIO_ERROR_OFFSET;
|
||||
}
|
||||
fseek(fp, 4, SEEK_SET);
|
||||
unsigned char buf[4];
|
||||
if (fread(buf, 1, sizeof(buf), fp) != sizeof(buf)) {
|
||||
return MMIO_ERROR_OFFSET;
|
||||
}
|
||||
uint32_t peri_base = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0;
|
||||
uint32_t gpio_base = peri_base + GPIO_BASE_OFFSET;
|
||||
fclose(fp);
|
||||
|
||||
int fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
|
||||
if (fd == -1) {
|
||||
// Error opening /dev/gpiomem.
|
||||
return MMIO_ERROR_DEVMEM;
|
||||
}
|
||||
// Map GPIO memory to location in process space.
|
||||
pi_2_mmio_gpio = (uint32_t*)mmap(NULL, GPIO_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, gpio_base);
|
||||
close(fd);
|
||||
if (pi_2_mmio_gpio == MAP_FAILED) {
|
||||
// Don't save the result if the memory mapping failed.
|
||||
pi_2_mmio_gpio = NULL;
|
||||
return MMIO_ERROR_MMAP;
|
||||
}
|
||||
}
|
||||
return MMIO_SUCCESS;
|
||||
}
|
||||
62
src/main/c/adafruit/Raspberry_Pi_2/pi_2_mmio.h
Normal file
62
src/main/c/adafruit/Raspberry_Pi_2/pi_2_mmio.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2014 Adafruit Industries
|
||||
// Author: Tony DiCola
|
||||
// Based on code from Gert van Loo & Dom: http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// Simple fast memory-mapped GPIO library for the Raspberry Pi.
|
||||
#ifndef PI_2_MMIO_H
|
||||
#define PI_2_MMIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MMIO_SUCCESS 0
|
||||
#define MMIO_ERROR_DEVMEM -1
|
||||
#define MMIO_ERROR_MMAP -2
|
||||
#define MMIO_ERROR_OFFSET -3
|
||||
|
||||
extern volatile uint32_t* pi_2_mmio_gpio;
|
||||
|
||||
int pi_2_mmio_init(void);
|
||||
|
||||
static inline void pi_2_mmio_set_input(const int gpio_number) {
|
||||
// Set GPIO register to 000 for specified GPIO number.
|
||||
*(pi_2_mmio_gpio+((gpio_number)/10)) &= ~(7<<(((gpio_number)%10)*3));
|
||||
}
|
||||
|
||||
static inline void pi_2_mmio_set_output(const int gpio_number) {
|
||||
// First set to 000 using input function.
|
||||
pi_2_mmio_set_input(gpio_number);
|
||||
// Next set bit 0 to 1 to set output.
|
||||
*(pi_2_mmio_gpio+((gpio_number)/10)) |= (1<<(((gpio_number)%10)*3));
|
||||
}
|
||||
|
||||
static inline void pi_2_mmio_set_high(const int gpio_number) {
|
||||
*(pi_2_mmio_gpio+7) = 1 << gpio_number;
|
||||
}
|
||||
|
||||
static inline void pi_2_mmio_set_low(const int gpio_number) {
|
||||
*(pi_2_mmio_gpio+10) = 1 << gpio_number;
|
||||
}
|
||||
|
||||
static inline uint32_t pi_2_mmio_input(const int gpio_number) {
|
||||
return *(pi_2_mmio_gpio+13) & (1 << gpio_number);
|
||||
}
|
||||
|
||||
#endif
|
||||
66
src/main/c/adafruit/common_dht_read.c
Normal file
66
src/main/c/adafruit/common_dht_read.c
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2014 Adafruit Industries
|
||||
// Author: Tony DiCola
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "common_dht_read.h"
|
||||
|
||||
void busy_wait_milliseconds(uint32_t millis) {
|
||||
// Set delay time period.
|
||||
struct timeval deltatime;
|
||||
deltatime.tv_sec = millis / 1000;
|
||||
deltatime.tv_usec = (millis % 1000) * 1000;
|
||||
struct timeval walltime;
|
||||
// Get current time and add delay to find end time.
|
||||
gettimeofday(&walltime, NULL);
|
||||
struct timeval endtime;
|
||||
timeradd(&walltime, &deltatime, &endtime);
|
||||
// Tight loop to waste time (and CPU) until enough time as elapsed.
|
||||
while (timercmp(&walltime, &endtime, <)) {
|
||||
gettimeofday(&walltime, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void sleep_milliseconds(uint32_t millis) {
|
||||
struct timespec sleep;
|
||||
sleep.tv_sec = millis / 1000;
|
||||
sleep.tv_nsec = (millis % 1000) * 1000000L;
|
||||
while (clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep, &sleep) && errno == EINTR);
|
||||
}
|
||||
|
||||
void set_max_priority(void) {
|
||||
struct sched_param sched;
|
||||
memset(&sched, 0, sizeof(sched));
|
||||
// Use FIFO scheduler with highest priority for the lowest chance of the kernel context switching.
|
||||
sched.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||
sched_setscheduler(0, SCHED_FIFO, &sched);
|
||||
}
|
||||
|
||||
void set_default_priority(void) {
|
||||
struct sched_param sched;
|
||||
memset(&sched, 0, sizeof(sched));
|
||||
// Go back to default scheduler with default 0 priority.
|
||||
sched.sched_priority = 0;
|
||||
sched_setscheduler(0, SCHED_OTHER, &sched);
|
||||
}
|
||||
51
src/main/c/adafruit/common_dht_read.h
Normal file
51
src/main/c/adafruit/common_dht_read.h
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2014 Adafruit Industries
|
||||
// Author: Tony DiCola
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#ifndef COMMON_DHT_READ_H
|
||||
#define COMMON_DHT_READ_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Define errors and return values.
|
||||
#define DHT_ERROR_TIMEOUT -1
|
||||
#define DHT_ERROR_CHECKSUM -2
|
||||
#define DHT_ERROR_ARGUMENT -3
|
||||
#define DHT_ERROR_GPIO -4
|
||||
#define DHT_SUCCESS 0
|
||||
|
||||
// Define sensor types.
|
||||
#define DHT11 11
|
||||
#define DHT22 22
|
||||
#define AM2302 22
|
||||
|
||||
// Busy wait delay for most accurate timing, but high CPU usage.
|
||||
// Only use this for short periods of time (a few hundred milliseconds at most)!
|
||||
void busy_wait_milliseconds(uint32_t millis);
|
||||
|
||||
// General delay that sleeps so CPU usage is low, but accuracy is potentially bad.
|
||||
void sleep_milliseconds(uint32_t millis);
|
||||
|
||||
// Increase scheduling priority and algorithm to try to get 'real time' results.
|
||||
void set_max_priority(void);
|
||||
|
||||
// Drop scheduling priority back to normal/default.
|
||||
void set_default_priority(void);
|
||||
|
||||
#endif
|
||||
4
src/main/c/compile.sh
Executable file
4
src/main/c/compile.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm testAdafruit;
|
||||
gcc -Wall -I. -Iadafruit/Raspberry_Pi_2 adafruit/common_dht_read.c adafruit/Raspberry_Pi_2/pi_2_mmio.c adafruit/Raspberry_Pi_2/pi_2_dht_read.c testAdafruit.c -o testAdafruit
|
||||
30
src/main/c/testAdafruit.c
Normal file
30
src/main/c/testAdafruit.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "adafruit/Raspberry_Pi_2/pi_2_dht_read.h"
|
||||
|
||||
int main( void )
|
||||
{
|
||||
printf( "Raspberry Pi 2 DHT11 test program\n" );
|
||||
|
||||
int i;
|
||||
int res;
|
||||
float humidity = 0, temperature = 0;
|
||||
int sensor = 11;
|
||||
int pin = 4;
|
||||
for (i = 1; i < 15; ++i){
|
||||
res = pi_2_dht_read(sensor, pin, &humidity, &temperature);
|
||||
if(res == 0){
|
||||
printf("Temperature : %f\n", temperature);
|
||||
printf("Humidity : %f\n", humidity);
|
||||
}
|
||||
else{
|
||||
printf("Error when reading from sensor : %d\n", res);
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
38
src/main/java/nl/lengrand/therobottle/GreetApplication.java
Normal file
38
src/main/java/nl/lengrand/therobottle/GreetApplication.java
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package nl.lengrand.therobottle;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
import io.helidon.common.CollectionsHelper;
|
||||
|
||||
/**
|
||||
* Simple Application that produces a greeting message.
|
||||
*/
|
||||
@ApplicationScoped
|
||||
@ApplicationPath("/")
|
||||
public class GreetApplication extends Application {
|
||||
|
||||
@Override
|
||||
public Set<Class<?>> getClasses() {
|
||||
return CollectionsHelper.setOf(GreetResource.class);
|
||||
}
|
||||
}
|
||||
130
src/main/java/nl/lengrand/therobottle/GreetResource.java
Normal file
130
src/main/java/nl/lengrand/therobottle/GreetResource.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package nl.lengrand.therobottle;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.json.Json;
|
||||
import javax.json.JsonBuilderFactory;
|
||||
import javax.json.JsonObject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
/**
|
||||
* A simple JAX-RS resource to greet you. Examples:
|
||||
*
|
||||
* Get default greeting message:
|
||||
* curl -X GET http://localhost:8080/greet
|
||||
*
|
||||
* Get greeting message for Joe:
|
||||
* curl -X GET http://localhost:8080/greet/Joe
|
||||
*
|
||||
* Change greeting
|
||||
* curl -X PUT -H "Content-Type: application/json" -d '{"greeting" : "Howdy"}' http://localhost:8080/greet/greeting
|
||||
*
|
||||
* The message is returned as a JSON object.
|
||||
*/
|
||||
@Path("/greet")
|
||||
@RequestScoped
|
||||
public class GreetResource {
|
||||
|
||||
private static final JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap());
|
||||
|
||||
/**
|
||||
* The greeting message provider.
|
||||
*/
|
||||
private final GreetingProvider greetingProvider;
|
||||
|
||||
/**
|
||||
* Using constructor injection to get a configuration property.
|
||||
* By default this gets the value from META-INF/microprofile-config
|
||||
*
|
||||
* @param greetingConfig the configured greeting message
|
||||
*/
|
||||
@Inject
|
||||
public GreetResource(GreetingProvider greetingConfig) {
|
||||
this.greetingProvider = greetingConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a wordly greeting message.
|
||||
*
|
||||
* @return {@link JsonObject}
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:designforextension")
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public JsonObject getDefaultMessage() {
|
||||
return createResponse("World");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a greeting message using the name that was provided.
|
||||
*
|
||||
* @param name the name to greet
|
||||
* @return {@link JsonObject}
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:designforextension")
|
||||
@Path("/{name}")
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public JsonObject getMessage(@PathParam("name") String name) {
|
||||
return createResponse(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the greeting to use in future messages.
|
||||
*
|
||||
* @param jsonObject JSON containing the new greeting
|
||||
* @return {@link Response}
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:designforextension")
|
||||
@Path("/greeting")
|
||||
@PUT
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response updateGreeting(JsonObject jsonObject) {
|
||||
|
||||
if (!jsonObject.containsKey("greeting")) {
|
||||
JsonObject entity = JSON.createObjectBuilder()
|
||||
.add("error", "No greeting provided")
|
||||
.build();
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity(entity).build();
|
||||
}
|
||||
|
||||
String newGreeting = jsonObject.getString("greeting");
|
||||
|
||||
greetingProvider.setMessage(newGreeting);
|
||||
return Response.status(Response.Status.NO_CONTENT).build();
|
||||
}
|
||||
|
||||
private JsonObject createResponse(String who) {
|
||||
String msg = String.format("%s %s!", greetingProvider.getMessage(), who);
|
||||
|
||||
return JSON.createObjectBuilder()
|
||||
.add("message", msg)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
49
src/main/java/nl/lengrand/therobottle/GreetingProvider.java
Normal file
49
src/main/java/nl/lengrand/therobottle/GreetingProvider.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package nl.lengrand.therobottle;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
|
||||
/**
|
||||
* Provider for greeting message.
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class GreetingProvider {
|
||||
private final AtomicReference<String> message = new AtomicReference<>();
|
||||
|
||||
/**
|
||||
* Create a new greeting provider, reading the message from configuration.
|
||||
*
|
||||
* @param message greeting to use
|
||||
*/
|
||||
@Inject
|
||||
public GreetingProvider(@ConfigProperty(name = "app.greeting") String message) {
|
||||
this.message.set(message);
|
||||
}
|
||||
|
||||
String getMessage() {
|
||||
return message.get();
|
||||
}
|
||||
|
||||
void setMessage(String message) {
|
||||
this.message.set(message);
|
||||
}
|
||||
}
|
||||
69
src/main/java/nl/lengrand/therobottle/Main.java
Normal file
69
src/main/java/nl/lengrand/therobottle/Main.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package nl.lengrand.therobottle;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.LogManager;
|
||||
|
||||
import io.helidon.microprofile.server.Server;
|
||||
|
||||
/**
|
||||
* The application main class.
|
||||
*/
|
||||
public final class Main {
|
||||
|
||||
/**
|
||||
* Cannot be instantiated.
|
||||
*/
|
||||
private Main() { }
|
||||
|
||||
/**
|
||||
* Application main entry point.
|
||||
* @param args command line arguments
|
||||
* @throws IOException if there are problems reading logging properties
|
||||
*/
|
||||
public static void main(final String[] args) throws IOException {
|
||||
// load logging configuration
|
||||
setupLogging();
|
||||
|
||||
// start the server
|
||||
Server server = startServer();
|
||||
|
||||
System.out.println("http://localhost:" + server.port() + "/greet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the server.
|
||||
* @return the created {@link Server} instance
|
||||
*/
|
||||
static Server startServer() {
|
||||
// Server will automatically pick up configuration from
|
||||
// microprofile-config.properties
|
||||
// and Application classes annotated as @ApplicationScoped
|
||||
return Server.create().start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure logging from logging.properties file.
|
||||
*/
|
||||
private static void setupLogging() throws IOException {
|
||||
try (InputStream is = Main.class.getResourceAsStream("/logging.properties")) {
|
||||
LogManager.getLogManager().readConfiguration(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/main/java/nl/lengrand/therobottle/ReactiveService.java
Normal file
39
src/main/java/nl/lengrand/therobottle/ReactiveService.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package nl.lengrand.therobottle;
|
||||
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.helidon.microprofile.server.RoutingPath;
|
||||
import io.helidon.security.SecurityContext;
|
||||
import io.helidon.webserver.Routing;
|
||||
import io.helidon.webserver.Service;
|
||||
|
||||
/**
|
||||
* TODO javadoc.
|
||||
*/
|
||||
@ApplicationScoped
|
||||
@RoutingPath("/reactive")
|
||||
public class ReactiveService implements Service {
|
||||
@Inject
|
||||
private SecurityContext securityContext;
|
||||
|
||||
@Override
|
||||
public void update(Routing.Rules rules) {
|
||||
rules.get("/", (req, res) -> res.send("Context: " + securityContext));
|
||||
}
|
||||
}
|
||||
27
src/main/java/nl/lengrand/therobottle/Robottle.java
Normal file
27
src/main/java/nl/lengrand/therobottle/Robottle.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package nl.lengrand.therobottle;
|
||||
|
||||
public class Robottle {
|
||||
|
||||
// public static void main(String[] args) throws InterruptedException, ExecutionException {
|
||||
// Dht11Driver theDriver = new Dht11Driver();
|
||||
// theDriver.sayHello();
|
||||
//
|
||||
// FaunaApi api = new FaunaApi();
|
||||
// Thread.sleep(1000);
|
||||
//
|
||||
//// Let's see if it runs until tomorrow!
|
||||
// while(true){
|
||||
// float [] res = theDriver.getTemperatureAndHumidity();
|
||||
// if(res[0] != 0 && res[1] != 0){
|
||||
// System.out.println("Sending " + res[0] + " " + res[1]);
|
||||
// api.add(res);
|
||||
// api.update(res);
|
||||
// }
|
||||
// else{
|
||||
// System.out.println("Incorrect data!" + res[0] + " " + res[1]);
|
||||
// }
|
||||
// Thread.sleep(10000);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package nl.lengrand.therobottle.driver;
|
||||
|
||||
public class Dht11Driver {
|
||||
|
||||
static {
|
||||
System.loadLibrary("dht11");
|
||||
}
|
||||
|
||||
public native void sayHello();
|
||||
|
||||
public native float[] getTemperatureAndHumidity();
|
||||
}
|
||||
65
src/main/java/nl/lengrand/therobottle/fauna/Connection.java
Normal file
65
src/main/java/nl/lengrand/therobottle/fauna/Connection.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package nl.lengrand.therobottle.fauna;
|
||||
|
||||
import com.faunadb.client.FaunaClient;
|
||||
import com.faunadb.client.query.Language;
|
||||
import com.faunadb.client.types.Value;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.faunadb.client.query.Language.*;
|
||||
|
||||
public class Connection {
|
||||
|
||||
public static final String API_KEY_NAME = "ROBOTTLE_KEY";
|
||||
public final static String DB_NAME = "robottle";
|
||||
public final static String COLLECTION_NAME = "sensors";
|
||||
public final static String UPDATE_DEVICE_NAME = "robottle_00";
|
||||
public final static String INDEX_NAME = "sensor_data";
|
||||
public final static String INDEX_ALL_NAME = "all_sensors";
|
||||
|
||||
private FaunaClient client;
|
||||
|
||||
public Connection(){
|
||||
}
|
||||
|
||||
private boolean isInit(){
|
||||
return client != null;
|
||||
}
|
||||
|
||||
public void init(){
|
||||
try {
|
||||
this.client = createConnection();
|
||||
} catch (ExecutionException | InterruptedException | ConnectionException e) {
|
||||
System.out.println("Problem while initializing connection with FaunaDb");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private String getKey() {
|
||||
return System.getenv(API_KEY_NAME);
|
||||
}
|
||||
|
||||
private String getDbKey(FaunaClient adminClient) throws InterruptedException, ExecutionException {
|
||||
Value keyResults = adminClient.query(
|
||||
CreateKey(Obj("database", Database(Language.Value(DB_NAME)), "role", Language.Value("server")))
|
||||
).get();
|
||||
|
||||
return keyResults.at("secret").to(String.class).get();
|
||||
}
|
||||
|
||||
public FaunaClient createConnection() throws ExecutionException, InterruptedException, ConnectionException {
|
||||
FaunaClient adminClient = this.createAdminConnection();
|
||||
return adminClient.newSessionClient(getDbKey(adminClient));
|
||||
}
|
||||
|
||||
public FaunaClient createAdminConnection() throws ConnectionException {
|
||||
if(getKey() == null) throw new ConnectionException("Local API key not found " + API_KEY_NAME );
|
||||
return FaunaClient.builder()
|
||||
.withSecret(getKey())
|
||||
.build();
|
||||
}
|
||||
|
||||
public FaunaClient getClient(){
|
||||
return client;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package nl.lengrand.therobottle.fauna;
|
||||
|
||||
public class ConnectionException extends Exception {
|
||||
public ConnectionException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
}
|
||||
47
src/main/java/nl/lengrand/therobottle/fauna/FaunaApi.java
Normal file
47
src/main/java/nl/lengrand/therobottle/fauna/FaunaApi.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package nl.lengrand.therobottle.fauna;
|
||||
|
||||
import com.faunadb.client.query.Language;
|
||||
import com.faunadb.client.types.Value;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.faunadb.client.query.Language.*;
|
||||
import static fauna.Connection.*;
|
||||
|
||||
public class FaunaApi {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
public FaunaApi(){
|
||||
this.connection = new Connection();
|
||||
connection.init();
|
||||
}
|
||||
|
||||
public void add(float[] res) throws ExecutionException, InterruptedException {
|
||||
Value addDataResult = connection.getClient().query(
|
||||
Create(
|
||||
Collection(Language.Value(COLLECTION_NAME)),
|
||||
Obj("data",
|
||||
Obj( "temperature", Language.Value(res[0]), "humidity", Language.Value(res[1]) )
|
||||
)
|
||||
)
|
||||
).get();
|
||||
System.out.println("Added sensor data to collection " + COLLECTION_NAME + ":\n " + addDataResult + "\n");
|
||||
}
|
||||
|
||||
public void update(float[] res) throws ExecutionException, InterruptedException {
|
||||
Value updateDataResult =
|
||||
connection.getClient().query(
|
||||
Update(
|
||||
Select(Language.Value("ref"), Get(Match(Index(INDEX_NAME), Language.Value(UPDATE_DEVICE_NAME)))),
|
||||
Obj("data",
|
||||
Obj(
|
||||
"temperature", Language.Value(res[0]),
|
||||
"humidity", Language.Value(res[1])
|
||||
)
|
||||
)
|
||||
)
|
||||
).get();
|
||||
System.out.println("Updated sensor data from collection " + COLLECTION_NAME + ":\n " + updateDataResult + "\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package nl.lengrand.therobottle.fauna.setup;
|
||||
|
||||
import com.faunadb.client.FaunaClient;
|
||||
import com.faunadb.client.types.Value;
|
||||
import fauna.Connection;
|
||||
import fauna.ConnectionException;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.faunadb.client.query.Language.*;
|
||||
import static fauna.Connection.*;
|
||||
|
||||
/*
|
||||
Used to create the database and indexes. Should be run only once!
|
||||
*/
|
||||
public class FaunaDbSetup {
|
||||
|
||||
public static void main(String[] args) throws ExecutionException, InterruptedException, ConnectionException {
|
||||
System.out.println("Setting up Database " + DB_NAME);
|
||||
|
||||
Connection connection = new Connection();
|
||||
|
||||
FaunaClient adminClient = connection.createAdminConnection();
|
||||
|
||||
createDatabase(adminClient);
|
||||
Thread.sleep(1000);
|
||||
FaunaClient dbClient = connection.createConnection();
|
||||
|
||||
createCollection(dbClient);
|
||||
Thread.sleep(1000);
|
||||
|
||||
createIndex(dbClient);
|
||||
Thread.sleep(1000);
|
||||
|
||||
createAllIndex(dbClient);
|
||||
Thread.sleep(1000);
|
||||
|
||||
createInitialValue(dbClient);
|
||||
|
||||
adminClient.close();
|
||||
System.out.println("Client closed");
|
||||
}
|
||||
|
||||
private static String getDbKey(FaunaClient adminClient) throws InterruptedException, ExecutionException {
|
||||
Value keyResults = adminClient.query(
|
||||
CreateKey(Obj("database", Database(Language.Value(DB_NAME)), "role", Language.Value("server")))
|
||||
).get();
|
||||
|
||||
return keyResults.at("secret").to(String.class).get();
|
||||
}
|
||||
|
||||
private static void createIndex(FaunaClient dbClient) throws InterruptedException, ExecutionException {
|
||||
Value indexResults = dbClient.query(
|
||||
CreateIndex(
|
||||
Obj("name", Language.Value(INDEX_NAME),
|
||||
"source", Collection(Language.Value(COLLECTION_NAME)),
|
||||
"unique", Language.Value(true),
|
||||
"terms", Arr(Obj("field", Arr(Language.Value("data"), Language.Value("name"))))
|
||||
)
|
||||
)
|
||||
).get();
|
||||
System.out.println("Create name index for " + DB_NAME + ":\n " + indexResults + "\n");
|
||||
}
|
||||
|
||||
private static void createAllIndex(FaunaClient dbClient) throws InterruptedException, ExecutionException {
|
||||
Value indexResults = dbClient.query(
|
||||
CreateIndex(
|
||||
Obj("name", Language.Value(INDEX_ALL_NAME),
|
||||
"source", Collection(Language.Value(COLLECTION_NAME))
|
||||
)
|
||||
)
|
||||
).get();
|
||||
System.out.println("Create all index for " + DB_NAME + ":\n " + indexResults + "\n");
|
||||
}
|
||||
|
||||
|
||||
private static void createCollection(FaunaClient dbClient) throws InterruptedException, ExecutionException {
|
||||
Value collectionResults = dbClient.query(
|
||||
CreateCollection(
|
||||
Obj("name", Language.Value(COLLECTION_NAME), "history_days", null)
|
||||
)
|
||||
).get();
|
||||
System.out.println("Create Collection for " + DB_NAME + ":\n " + collectionResults + "\n");
|
||||
}
|
||||
|
||||
private static void createDatabase(FaunaClient adminClient) {
|
||||
adminClient.query(
|
||||
CreateDatabase(
|
||||
Obj("name", Language.Value(DB_NAME))
|
||||
)
|
||||
);
|
||||
|
||||
System.out.println("Db created");
|
||||
}
|
||||
|
||||
public static void createInitialValue(FaunaClient client) throws ExecutionException, InterruptedException {
|
||||
Value init = client.query(
|
||||
Create(
|
||||
Collection(Language.Value(COLLECTION_NAME)),
|
||||
Obj("data",
|
||||
Obj("name", Language.Value(UPDATE_DEVICE_NAME))
|
||||
)
|
||||
)
|
||||
).get();
|
||||
System.out.println("Added initial item to collection " + COLLECTION_NAME + ":\n " + init + "\n");
|
||||
}
|
||||
}
|
||||
20
src/main/java/nl/lengrand/therobottle/package-info.java
Normal file
20
src/main/java/nl/lengrand/therobottle/package-info.java
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Quickstart MicroProfile example.
|
||||
*/
|
||||
package nl.lengrand.therobottle;
|
||||
26
src/main/resources/META-INF/beans.xml
Normal file
26
src/main/resources/META-INF/beans.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
|
||||
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
||||
http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
|
||||
version="2.0"
|
||||
bean-discovery-mode="annotated">
|
||||
</beans>
|
||||
22
src/main/resources/META-INF/microprofile-config.properties
Normal file
22
src/main/resources/META-INF/microprofile-config.properties
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# Application properties. This is the default greeting
|
||||
app.greeting=Hello
|
||||
|
||||
# Microprofile server properties
|
||||
server.port=8080
|
||||
server.host=0.0.0.0
|
||||
37
src/main/resources/logging.properties
Normal file
37
src/main/resources/logging.properties
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
# Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# Example Logging Configuration File
|
||||
# For more information see $JAVA_HOME/jre/lib/logging.properties
|
||||
|
||||
# Send messages to the console
|
||||
handlers=io.helidon.common.HelidonConsoleHandler
|
||||
|
||||
# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread
|
||||
java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n
|
||||
|
||||
# Global logging level. Can be overridden by specific loggers
|
||||
.level=INFO
|
||||
|
||||
# Component specific log levels
|
||||
#io.helidon.webserver.level=INFO
|
||||
#io.helidon.config.level=INFO
|
||||
#io.helidon.security.level=INFO
|
||||
#io.helidon.microprofile.level=INFO
|
||||
#io.helidon.common.level=INFO
|
||||
#io.netty.level=INFO
|
||||
#org.glassfish.jersey.level=INFO
|
||||
#org.jboss.weld=INFO
|
||||
96
src/test/java/nl/lengrand/therobottle/MainTest.java
Normal file
96
src/test/java/nl/lengrand/therobottle/MainTest.java
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package nl.lengrand.therobottle;
|
||||
|
||||
import javax.enterprise.inject.se.SeContainer;
|
||||
import javax.enterprise.inject.spi.CDI;
|
||||
import javax.json.JsonObject;
|
||||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.ClientBuilder;
|
||||
import javax.ws.rs.client.Entity;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import io.helidon.microprofile.server.Server;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class MainTest {
|
||||
private static Server server;
|
||||
|
||||
@BeforeAll
|
||||
public static void startTheServer() throws Exception {
|
||||
server = Main.startServer();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHelloWorld() {
|
||||
|
||||
Client client = ClientBuilder.newClient();
|
||||
|
||||
JsonObject jsonObject = client
|
||||
.target(getConnectionString("/greet"))
|
||||
.request()
|
||||
.get(JsonObject.class);
|
||||
Assertions.assertEquals("Hello World!", jsonObject.getString("message"),
|
||||
"default message");
|
||||
|
||||
jsonObject = client
|
||||
.target(getConnectionString("/greet/Joe"))
|
||||
.request()
|
||||
.get(JsonObject.class);
|
||||
Assertions.assertEquals("Hello Joe!", jsonObject.getString("message"),
|
||||
"hello Joe message");
|
||||
|
||||
Response r = client
|
||||
.target(getConnectionString("/greet/greeting"))
|
||||
.request()
|
||||
.put(Entity.entity("{\"greeting\" : \"Hola\"}", MediaType.APPLICATION_JSON));
|
||||
Assertions.assertEquals(204, r.getStatus(), "PUT status code");
|
||||
|
||||
jsonObject = client
|
||||
.target(getConnectionString("/greet/Jose"))
|
||||
.request()
|
||||
.get(JsonObject.class);
|
||||
Assertions.assertEquals("Hola Jose!", jsonObject.getString("message"),
|
||||
"hola Jose message");
|
||||
|
||||
r = client
|
||||
.target(getConnectionString("/metrics"))
|
||||
.request()
|
||||
.get();
|
||||
Assertions.assertEquals(200, r.getStatus(), "GET metrics status code");
|
||||
|
||||
r = client
|
||||
.target(getConnectionString("/health"))
|
||||
.request()
|
||||
.get();
|
||||
Assertions.assertEquals(200, r.getStatus(), "GET health status code");
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void destroyClass() {
|
||||
CDI<Object> current = CDI.current();
|
||||
((SeContainer) current).close();
|
||||
}
|
||||
|
||||
private String getConnectionString(String path) {
|
||||
return "http://localhost:" + server.port() + path;
|
||||
}
|
||||
}
|
||||
22
src/test/resources/META-INF/microprofile-config.properties
Normal file
22
src/test/resources/META-INF/microprofile-config.properties
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
|
||||
# Override configuration to use a random port for the unit tests
|
||||
config_ordinal=1000
|
||||
# Microprofile server properties
|
||||
server.port=-1
|
||||
server.host=0.0.0.0
|
||||
Reference in New Issue
Block a user