TTN Forum: schedule downlink after uplink
@avbentem
code:
data:privatelast updated:4 years ago
today
Build integrations remarkably fast!
You're viewing a public workflow template.
Sign up to customize, add steps, modify code and more.
Join 1,000,000+ developers using the Pipedream platform
steps.
trigger
HTTP API
Deploy to generate unique URL
This workflow runs on Pipedream's servers and is triggered by HTTP / Webhook requests.
steps.
decodeAndScheduleDownlink
auth
to use OAuth tokens and API keys in code via theauths object
params
Optional
code
Write any Node.jscodeand use anynpm package. You can alsoexport datafor use in later steps via return or this.key = 'value', pass input data to your code viaparams, and maintain state across executions with$checkpoint.
async (event, steps, params) => {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
}
88
const axios = require('axios');
const { headers, body } = event;
const { authorization } = params;

if (authorization && authorization !== headers.authorization) {
  await $respond({
    immediate: true,
    status: 401,
    body: 'Missing or incorrect Authorization header in request'
  });
  $end('Missing or incorrect Authorization header in request');
}

console.log('Got body', body);

// See https://www.thethingsnetwork.org/docs/applications/http/
// When using a Decoder in the application's Payload Formats in
// TTN Console, then body.payload_fields will be available too.
const bytes = Buffer.from(body.payload_raw, 'base64');

// Assuming a Kickstarter The Things Node, with the default sketch;
// see https://www.thethingsnetwork.org/docs/devices/node/
const events = {
  1: 'setup',
  2: 'interval',
  3: 'motion',
  4: 'button'
};

const decoded = {
  event: events[body.port] || 'unknown',
  battery: (bytes[0] << 8 | bytes[1]) / 1000,
  light: bytes[2] << 8 | bytes[3],
  // Sign-extend to 32 bits to support negative values, by shifting
  // 24 bits to the left (16 too far), followed by a sign-propagating
  // right shift of 16 bits, to effectively shift 8 bits:
  temperature: (bytes[4] << 24 >> 16 | bytes[5]) / 100
};

console.log('Decoded', decoded);

const rgb = {
  setup: 0b101, // magenta
  interval: 0b100, // red
  motion: null,
  button: 0b010 // green
}[decoded.event];

if (!rgb) {
  $end('No downlink needed');
}

const downlink = {
  dev_id: body.dev_id,
  port: 1,
  confirmed: false,
  schedule: 'replace',
  payload_raw: Buffer.from([rgb]).toString('base64')
};

const options = {
  url: body.downlink_url,
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  data: downlink
};

console.log('Will POST', options);

// As we want to schedule the downlink as soon as possible, we cannot use
// $send.http (which would send fully asynchronously, after the workflow
// runs, but would not count against workflow quota)
const response = await axios(options);

const result = `Sent downlink to ${options.url}, ${response.status} ${response.statusText}`;
console.log(result);

// The HTTP Integration doesn't really care about the response
await $respond({
  immediate: true,
  status: 202,
  body: result
});