Skip to content

Commit

Permalink
Undo Revert "Revert changes since 9b0af44"
Browse files Browse the repository at this point in the history
This reverts commit 2c31345.
  • Loading branch information
davidgs committed Nov 4, 2017
1 parent c14478f commit 6e6aefe
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ tivan
.idea
*~
*#
.DS_Store
35 changes: 35 additions & 0 deletions plugins/inputs/webhooks/particle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# particle webhooks

You should configure your Particle.io's Webhooks to point at the `webhooks` service. To do this go to `(https://console.particle.io/)[https://console.particle.io]` and click `Integrations > New Integration > Webhook`. In the resulting page set `URL` to `http://<my_ip>:1619/particle`, and under `Advanced Settings` click on `JSON` and add:

```
{
"influx_db": "your_measurement_name"
}
```

If required, enter your username and password, etc. and then click `Save`


## Events

Your Particle device should publish an event that contains a JSON in the form of:
```
String data = String::format("{ \"tags\" : {
\"tag_name\": \"tag_value\",
\"other_tag\": \"other_value\"
},
\"values\": {
\"value_name\": %f,
\"other_value\": %f,
}
}", value_value, other_value
);
Particle.publish("event_name", data, PRIVATE);
```
Escaping the "" is required in the source file on the Particle device.
The number of tag values and field values is not restricted so you can send as many values per webhook call as you'd like.



See [webhook doc](https://docs.particle.io/reference/webhooks/)
67 changes: 67 additions & 0 deletions plugins/inputs/webhooks/particle/particle_webhooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package particle

import (
"encoding/json"
"log"
"net/http"
"time"

"github.com/gorilla/mux"
"github.com/influxdata/telegraf"
)

type event struct {
Name string `json:"event"`
Data data `json:"data"`
TTL int `json:"ttl"`
PublishedAt string `json:"published_at"`
Database string `json:"influx_db"`
}

type data struct {
Tags map[string]string `json:"tags"`
Fields map[string]interface{} `json:"values"`
}

func newEvent() *event {
return &event{
Data: data{
Tags: make(map[string]string),
Fields: make(map[string]interface{}),
},
}
}

func (e *event) Time() (time.Time, error) {
return time.Parse("2006-01-02T15:04:05Z", e.PublishedAt)
}

type ParticleWebhook struct {
Path string
acc telegraf.Accumulator
}

func (rb *ParticleWebhook) Register(router *mux.Router, acc telegraf.Accumulator) {
router.HandleFunc(rb.Path, rb.eventHandler).Methods("POST")
log.Printf("I! Started the webhooks_particle on %s\n", rb.Path)
rb.acc = acc
}

func (rb *ParticleWebhook) eventHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
e := newEvent()
if err := json.NewDecoder(r.Body).Decode(e); err != nil {
log.Println(err)
w.WriteHeader(http.StatusBadRequest)
return
}

pTime, err := e.Time()
if err != nil {
pTime = time.Now()
log.Printf("error parsing particle event time: %s. Using telegraf host time instead: %s", e.PublishedAt, pTime)
}

rb.acc.AddFields(e.Name, e.Data.Fields, e.Data.Tags, pTime)
w.WriteHeader(http.StatusOK)
}
97 changes: 97 additions & 0 deletions plugins/inputs/webhooks/particle/particle_webhooks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package particle

import (
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/influxdata/telegraf/testutil"
)

func postWebhooks(rb *ParticleWebhook, eventBody string) *httptest.ResponseRecorder {
req, _ := http.NewRequest("POST", "/", strings.NewReader(eventBody))
w := httptest.NewRecorder()
w.Code = 500

rb.eventHandler(w, req)

return w
}

func TestNewItem(t *testing.T) {
t.Parallel()
var acc testutil.Accumulator
rb := &ParticleWebhook{Path: "/particle", acc: &acc}
resp := postWebhooks(rb, NewItemJSON())
if resp.Code != http.StatusOK {
t.Errorf("POST new_item returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK)
}

fields := map[string]interface{}{
"temp_c": 26.680000,
"temp_f": 80.024001,
"infrared": 528.0,
"lux": 0.0,
"humidity": 44.937500,
"pressure": 998.998901,
"altitude": 119.331436,
"broadband": 1266.0,
}

tags := map[string]string{
"id": "230035001147343438323536",
"location": "TravelingWilbury",
}

acc.AssertContainsTaggedFields(t, "temperature", fields, tags)
}

func TestUnknowItem(t *testing.T) {
t.Parallel()
var acc testutil.Accumulator
rb := &ParticleWebhook{Path: "/particle", acc: &acc}
resp := postWebhooks(rb, UnknowJSON())
if resp.Code != http.StatusOK {
t.Errorf("POST unknown returned HTTP status code %v.\nExpected %v", resp.Code, http.StatusOK)
}
}

func NewItemJSON() string {
return `
{
"event": "temperature",
"data": {
"tags": {
"id": "230035001147343438323536",
"location": "TravelingWilbury"
},
"values": {
"temp_c": 26.680000,
"temp_f": 80.024001,
"humidity": 44.937500,
"pressure": 998.998901,
"altitude": 119.331436,
"broadband": 1266,
"infrared": 528,
"lux": 0.0
}
},
"ttl": 60,
"published_at": "2017-09-28T21:54:10.897Z",
"coreid": "123456789938323536",
"userid": "1234ee123ac8e5ec1231a123d",
"version": 10,
"public": false,
"productID": 1234,
"name": "sensor",
"influx_db": "mydata"
}`
}

func UnknowJSON() string {
return `
{
"event": "roger"
}`
}

0 comments on commit 6e6aefe

Please sign in to comment.