diff --git a/Nodes/LED_control/Makefile b/Nodes/LED_control/Makefile new file mode 100644 index 0000000..7eb351d --- /dev/null +++ b/Nodes/LED_control/Makefile @@ -0,0 +1,50 @@ +# name of your application +APPLICATION = coap-example + +# If no BOARD is found in the environment, use this default: +BOARD ?= pba-d-01-kw2x + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../RIOT + +# enable default networking devides in the platform +USEMODULE += netdev_default + +# automatically initialize network interfaces for enabled devices +USEMODULE += auto_init_gnrc_netif + +# add minimal IPv6 support +USEMODULE += gnrc_ipv6_default + +# add ICMPv6 support (ping) +USEMODULE += gnrc_icmpv6_echo + +# add CoAP module +USEMODULE += gcoap + +# object dump allows use to print streams of bytes +USEMODULE += od + +# fmt allows use to format strings +USEMODULE += fmt + +USEMODULE += netutils +# Add also the shell, some shell commands +USEMODULE += shell +USEMODULE += shell_commands +USEMODULE += ps + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +DEVELHELP ?= 1 + +# The default size of GCOAP_PDU_BUF_SIZE can be too small for the response +# from the RD server. Use a larger value if the client drops response packet +# from RD server. +CFLAGS += -DCONFIG_GCOAP_PDU_BUF_SIZE=512 + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/Nodes/LED_control/README.md b/Nodes/LED_control/README.md new file mode 100644 index 0000000..9764c71 --- /dev/null +++ b/Nodes/LED_control/README.md @@ -0,0 +1,321 @@ +# CoAP basic example + +The Constrained Application Protocol (CoAP) is a specialized web transfer +protocol for use with constrained nodes and constrained (e.g., low-power, lossy) +networks. It has been standardized by the IETF in +[RFC 7252](https://datatracker.ietf.org/doc/html/rfc7252). + +Nodes can act both as clients (performing requests) and as servers (serving +requests). In this example the node will expose one resource at `/riot/board`, +which accepts GET requests and returns the board name in plain text. + +It also can perform CoAP requests to other nodes. The application exposes a +`coap` shell command to interact with these functionalities. + +We will be using the gcoap module from RIOT. For more detailed information and +advanced usages, check +[the documentation](https://doc.riot-os.org/group__net__gcoap.html). + +## Task 1 + +Verify that your device is exposing the resource correctly. + +**1. Build and flash the application. Open a serial communication:** +```sh +$ make all flash term +``` + +**2. On the RIOT shell, find your node IPv6 address by using the `ifconfig` command:** +```sh +> ifconfig +``` + +**The response should be similar to:** +``` +2022-03-30 13:51:14,836 # ifconfig +2022-03-30 13:51:14,840 # Iface 6 HWaddr: 3E:66 Channel: 26 NID: 0x23 +2022-03-30 13:51:14,844 # Long HWaddr: 5F:0F:7B:9D:AE:49:3E:E6 +2022-03-30 13:51:14,848 # TX-Power: 0dBm State: IDLE +2022-03-30 13:51:14,851 # AUTOACK ACK_REQ AUTOCCA +2022-03-30 13:51:14,856 # L2-PDU:102 MTU:1280 HL:64 6LO IPHC +2022-03-30 13:51:14,859 # Source address length: 8 +2022-03-30 13:51:14,862 # Link type: wireless +2022-03-30 13:51:14,867 # inet6 addr: fe80::5d0f:7b9d:ae49:3ee6 scope: link VAL +2022-03-30 13:51:14,874 # inet6 addr: 2001:db8::5d0f:7b9d:ae49:3ee6 scope: global VAL +2022-03-30 13:51:14,876 # inet6 group: ff02::1 +2022-03-30 13:51:14,877 # +``` + +**You should see one wireless interface.** +**Among other things, it has a MAC address (Long HWaddr), a maximum transmission unit (MTU) and one or more IPv6 addresses.** +**They are denoted `inet6 addr`. You may not see the one with `scope:global`.** +**In this case, one of the node's IPv6 addresses is `2001:db8::5d0f:7b9d:ae49:3ee6`.** + +**3. Make a coap GET request to your own node. Use your IP address from the previous step.** +**You can check how to use the `coap` shell command by typing:** +```sh +> coap help +``` + +**The default UDP port for CoAP servers is `5683`:** +```sh +> coap get 2001:db8::5d0f:7b9d:ae49:3ee6 5683 /.well-known/core +``` + +**You should get a response with `code 2.05` and the paths of the resources.** +``` +2022-03-30 19:44:17,534 # gcoap_cli: sending msg ID 37913, 23 bytes +2022-03-30 19:44:17,539 # gcoap: response Success, code 2.05, 13 bytes +2022-03-30 19:44:17,540 # +``` + +**4. Try to get the board name from the `/riot/board` resource, sending a GET request.** +**The command should look almost as the one in step 3, but with a different path at the end.** + +## Task 2 + +Add a new CoAP resource to the server to interact with LEDs on the board. Upon a +GET request it should return the status of the specific LED. When a PUT request +is received, the payload should used to set the new status of the LED. + +**NOTE: The CoAP server is implemented in `server.c`, that's where you are going** +**to work.** + +**1. Declare an array of GPIOs to control the LEDs:** +```C +static const gpio_t leds[] = { + LED0_PIN, + LED1_PIN, + LED2_PIN, +}; +``` +**2. Initialize the LED GPIOs inside the `server_init` function.** +```C +/* initialize LEDs and turn them off */ +for (unsigned i = 0; i < ARRAY_SIZE(leds); i++) { + gpio_init(leds[i], GPIO_OUT); + gpio_set(leds[i]); +} +``` + +**3. Register a new CoAP resource in the `_resources` array.** +**It should accept GET and PUT requests.** +**It should also match all requests to paths starting with `/led/`:** +```C +{ "/led/", COAP_GET | COAP_PUT | COAP_MATCH_SUBTREE, _led_handler, NULL }, +``` + +**4. Implement the resource handler function.** + +**Start by defining the function with the correct** +**[signature](https://doc.riot-os.org/group__net__gcoap.html#ga8f62887693fa63a7595565e44156806d):** +```C +static ssize_t _led_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx) +{ + (void) ctx; /* argument not used */ + + /* implement your handler here */ + + return 0; +} +``` + +**First we need to parse the URI, to know which LED was requested:** +```C +char uri[CONFIG_NANOCOAP_URI_MAX] = { 0 }; +/* get the request path, to know which LED is being requested */ +if (coap_get_uri_path(pdu, (uint8_t *)uri) <= 0) { + /* reply with an error if we could not parse the URI */ + return gcoap_response(pdu, buf, len, COAP_CODE_BAD_REQUEST); +} + +/* find the LED number, the URI should be /led/ */ +char *led_str = uri + strlen("/led/"); +unsigned led_number = atoi(led_str); + +/* verify that the number is valid, respond with an error otherwise */ +if (led_number >= ARRAY_SIZE(leds)) { + return gcoap_response(pdu, buf, len, COAP_CODE_BAD_REQUEST); +} +``` + +**Now we need to determine the type of request (GET or PUT):** +```C +ssize_t resp_len = 0; +int led_status = 0; +unsigned method = coap_method2flag(coap_get_code_detail(pdu)); + +switch (method) { +case COAP_PUT: /* on PUT, we set the status of the LED based on the payload */ + +case COAP_GET: /* on GET, we return the status of the LED in plain text */ + +} +``` + +**Let's implement the PUT request first:** +```C +case COAP_PUT: /* on PUT, we set the status of the LED based on the payload */ + /* check if there is a payload with a LED status */ + if (pdu->payload_len) { + led_status = atoi((char *)pdu->payload); + } else { + return gcoap_response(pdu, buf, len, COAP_CODE_BAD_REQUEST); + } + + if (led_status) { + gpio_clear(leds[led_number]); + } else { + gpio_set(leds[led_number]); + } + return gcoap_response(pdu, buf, len, COAP_CODE_CHANGED); + +``` + +**Now the response to a GET request:** +```C +case COAP_GET: /* on GET, we return the status of the LED in plain text */ + /* initialize the CoAP response */ + gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT); + + /* set the content format to plain text */ + coap_opt_add_format(pdu, COAP_FORMAT_TEXT); + + /* finish the options indicating that we will include a payload */ + resp_len = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD); + + /* get the current status of the LED, which is the inverted value of the GPIO */ + led_status = !gpio_read(leds[led_number]); + + /* based on the status, write the value of the payload to send */ + if (led_status) { + pdu->payload[0] = '1'; + } else { + pdu->payload[0] = '0'; + } + resp_len++; + return resp_len; +``` + +**5. Declare your handler function's prototype before `_resources` is declared:** +```C +static ssize_t _led_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx); +``` + +**6. Build and flash your application. Open the serial communication.** + +You should be able to interact with your own LEDs by sending messages to your +own IP address (`coap put`)...but that's not fun... + +## Task 3 + +Ask someone around for their IP address and try to turn some other board's LEDs +on. + +**1. Turn the LED 0 of some other board on:** +```sh +> coap put 2001:db8::814c:35fc:fd31:5fde 5683 /led/0 1 +``` +--- + +## CoRE Link Format (RFC 6690) + +[RFC 6690](https://datatracker.ietf.org/doc/html/rfc6690) defines a format to +express web linking for constrained nodes. It is usually utilized for resource +discovery (e.g. via the `/.well-known/core` resource or a resource directory). + +Let's see an example of a link format response (the line breaks are included +for clarity): + +``` +;ct=40;title="Sensor Index", +;rt="temperature-c";if="sensor", +;rt="light-lux";if="sensor";obs +``` + +This list of links contains 3 elements. Link in a list are separated by `,`. A +link is composed by a URI (enclosed in `< >`) and zero or more attributes. Each +attribute is separated by `;`. An attribute may or may not have a value. The key +and the value are separated by `=`. Attributes are key/values, expressing extra +information about the link. Some examples of attributes are: content type +(`ct`), resource type (`rt`), or the interface (`if`). + +--- + +**The next two tasks involve multiple nodes and a resource directory. The** +**complete diagram looks like the following:** + +![](diagram.jpg) + +## Task 4 + +Use the information from the `/.well-known/core` to find resources exposing +temperature and humidity readings of the room. + +**1. Using the provided IP address, perform a GET request to the nodes** +**`/.well-known/core` resource to find which resources it exposes.** +**Use the `coap` shell command as in task 1.** + +**2. Once you have found the resources, try getting the current temperature** +**and humidity values.** + +## Task 5 + +Discover the hidden sensor. Perform a lookup on a resource directory to find a +node that is exposing pressure and magnetic readings in the room. + +**1. Using the provided resource directory IP address, perform a GET request to** +**its `/.well-known/core` resource. The response will be in Link Format.** +**You need to find in the list of links, a resource where to perform a lookup.** +**According to the specification, the resource type of the lookup resource** +**should be `rt=core.rd-lookup-res`** + +**2. Once you have found the lookup resource, perform a GET request to it.** +**It should reply with the hidden sensor information.** + +**3. Finally, get the current pressure and magnetic values from the hidden sensor.** + +## Task 6 + +Make a pull request on GitHub with your changes. + +**1. Make sure you saved all changes. Switch to a new git branch:** +```sh +$ git checkout -b pr/add_my_sensors +``` + +**2. Configure your name and email, replace with your information:** +```sh +$ git config --global user.name "FIRST_NAME LAST_NAME" +$ git config --global user.email "MY_NAME@example.com" +``` + +**3. Stage your changes to be committed:** +```sh +$ git add . +``` + +**4. Add a new commit with the change. Adapt the commit message with your name:** +```sh +$ git commit -m "Add sensor CoAP resources" +``` + +**5. Make a fork of [the project](https://github.com/smartuni/exercises)** +**on your own account, using GitHub's website.** + +**6. Add the new remote to your repository. Replace with the correct username** +```sh +$ git remote add upstream https://github.com//exercises.git +``` + +**7. You will need to generate a token to login while you push your changes.** +**Generate a new token following** +**[this guide](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token). COPY IT SOMEWHERE!** + +**7. Push the new branch to your repository:** +```sh +$ git push upstream pr/add_my_sensors +``` +**When prompted for a password, use your token.** + +**8. Create a new ull request using GitHub website** diff --git a/Nodes/LED_control/client.c b/Nodes/LED_control/client.c new file mode 100644 index 0000000..06902bb --- /dev/null +++ b/Nodes/LED_control/client.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2015-2017 Ken Bannister. All rights reserved. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup examples + * @{ + * + * @file + * @brief gcoap CLI support + * + * @author Ken Bannister + * @author Hauke Petersen + * + * @} + */ + +#include +#include +#include +#include + +#include "shell.h" +#include "fmt.h" +#include "net/gcoap.h" +#include "net/utils.h" +#include "od.h" + +#include "gcoap_example.h" + +uint16_t req_count = 0; + +/* + * Response callback. + */ +static void _resp_handler(const gcoap_request_memo_t *memo, coap_pkt_t* pdu, + const sock_udp_ep_t *remote) +{ + (void)remote; /* not interested in the source currently */ + + if (memo->state == GCOAP_MEMO_TIMEOUT) { + printf("gcoap: timeout for msg ID %02u\n", coap_get_id(pdu)); + return; + } + else if (memo->state != GCOAP_MEMO_RESP) { + printf("gcoap: error in response\n"); + printf("state: %d\n", memo->state); + return; + } + + char *class_str = (coap_get_code_class(pdu) == COAP_CLASS_SUCCESS) ? "Success" : "Error"; + + printf("gcoap: response %s, code %1u.%02u", class_str, + coap_get_code_class(pdu), + coap_get_code_detail(pdu)); + if (pdu->payload_len) { + unsigned content_type = coap_get_content_type(pdu); + if (content_type == COAP_FORMAT_TEXT + || content_type == COAP_FORMAT_LINK + || coap_get_code_class(pdu) == COAP_CLASS_CLIENT_FAILURE + || coap_get_code_class(pdu) == COAP_CLASS_SERVER_FAILURE) { + /* Expecting diagnostic payload in failure cases */ + printf(", %u bytes\n%.*s\n", pdu->payload_len, pdu->payload_len, + (char *)pdu->payload); + } + else { + printf(", %u bytes\n", pdu->payload_len); + od_hex_dump(pdu->payload, pdu->payload_len, OD_WIDTH_DEFAULT); + } + } + else { + printf(", empty payload\n"); + } +} + +static bool _parse_endpoint(sock_udp_ep_t *remote, + const char *addr_str, const char *port_str) +{ + netif_t *netif; + + /* parse hostname */ + if (netutils_get_ipv6((ipv6_addr_t *)&remote->addr, &netif, addr_str) < 0) { + puts("gcoap_cli: unable to parse destination address"); + return false; + } + remote->netif = netif ? netif_get_id(netif) : SOCK_ADDR_ANY_NETIF; + remote->family = AF_INET6; + + /* parse port */ + remote->port = atoi(port_str); + if (remote->port == 0) { + puts("gcoap_cli: unable to parse destination port"); + return false; + } + + return true; +} + +static size_t _send(uint8_t *buf, size_t len, char *addr_str, char *port_str) +{ + size_t bytes_sent; + sock_udp_ep_t remote; + + if (!_parse_endpoint(&remote, addr_str, port_str)) { + return 0; + } + + bytes_sent = gcoap_req_send(buf, len, &remote, _resp_handler, NULL); + if (bytes_sent > 0) { + req_count++; + } + return bytes_sent; +} + +static int _print_usage(char **argv) +{ + printf("usage: %s info\n", argv[0]); + printf(" %s [%%iface] [data]\n",argv[0]); + return 1; +} + +static int _coap_info_cmd(void) +{ + uint8_t open_reqs = gcoap_op_state(); + + printf("CoAP server is listening on port %u\n", CONFIG_GCOAP_PORT); + printf(" CLI requests sent: %u\n", req_count); + printf("CoAP open requests: %u\n", open_reqs); + return 0; +} + +/* map a string to a coap method code */ +int _method_str_to_code(const char *method) +{ + if (!strcmp(method, "get")) { + return COAP_METHOD_GET; + } + else if (!strcmp(method, "post")) { + return COAP_METHOD_POST; + } + else if (!strcmp(method, "put")) { + return COAP_METHOD_PUT; + } + else if (!strcmp(method, "delete")) { + return COAP_METHOD_DELETE; + } + + printf("Unknown method: %s\n", method); + return -1; +} + +int gcoap_cli_cmd(int argc, char **argv) +{ + + uint8_t buf[CONFIG_GCOAP_PDU_BUF_SIZE]; + coap_pkt_t pdu; + size_t len; + int position = 1; + + /* parse user input */ + if (argc == 1) { + /* invalid number of arguments, show help for the command */ + return _print_usage(argv); + } + + if (strcmp(argv[position], "info") == 0) { + return _coap_info_cmd(); + } + + if ((argc != 5) && (argc != 6)) { + /* invalid number of arguments, show help for the command */ + return _print_usage(argv); + } + + /* determine which method to use */ + int code = _method_str_to_code(argv[position]); + if (code < 0) { + /* unknown method, show help */ + return _print_usage(argv); + } + + position ++; + + char *addr = argv[position++]; + char *port = argv[position++]; + char *path = argv[position++]; + + /* simple check for the path */ + if (!path || path[0] != '/') { + return _print_usage(argv); + } + + char *data = NULL; + size_t data_len = 0; + if (argc == 6) { + data = argv[position++]; + data_len = strlen(data); + } + printf("%s\n", path); + /* initialize the CoAP request */ + gcoap_req_init(&pdu, buf, CONFIG_GCOAP_PDU_BUF_SIZE, code, path); + + /* send a confirmable message */ + coap_hdr_set_type(pdu.hdr, COAP_TYPE_CON); + + /* if there is data, we specify the plain text format and copy the payload */ + if (data_len) { + coap_opt_add_format(&pdu, COAP_FORMAT_TEXT); + + len = coap_opt_finish(&pdu, COAP_OPT_FINISH_PAYLOAD); + if (pdu.payload_len >= data_len) { + memcpy(pdu.payload, data, data_len); + len += data_len; + } + else { + puts("The buffer is too small, reduce the message length"); + return 1; + } + } else { + len = coap_opt_finish(&pdu, COAP_OPT_FINISH_NONE); + } + + printf("gcoap_cli: sending msg ID %u, %u bytes\n", coap_get_id(&pdu), (unsigned) len); + if (!_send(buf, len, addr, port)) { + puts("gcoap_cli: msg send failed"); + return -1; + } + return 0; +} + +/* define CoAP shell command */ +SHELL_COMMAND(coap, "Perform CoAP operations", gcoap_cli_cmd); diff --git a/Nodes/LED_control/diagram.jpg b/Nodes/LED_control/diagram.jpg new file mode 100644 index 0000000..793684c Binary files /dev/null and b/Nodes/LED_control/diagram.jpg differ diff --git a/Nodes/LED_control/gcoap_example.h b/Nodes/LED_control/gcoap_example.h new file mode 100644 index 0000000..aa4f7e8 --- /dev/null +++ b/Nodes/LED_control/gcoap_example.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup examples + * @{ + * + * @file + * @brief gcoap example + * + * @author Ken Bannister + */ + +#ifndef GCOAP_EXAMPLE_H +#define GCOAP_EXAMPLE_H + +#include +#include +#include +#include + +#include "fmt.h" +#include "net/gcoap.h" +#include "net/utils.h" +#include "od.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint16_t req_count; /**< Counts requests sent by CLI. */ + +/** + * @brief Registers the CoAP resources exposed in the example app + * + * Run this exactly one during startup. + */ +void server_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GCOAP_EXAMPLE_H */ +/** @} */ diff --git a/Nodes/LED_control/main.c b/Nodes/LED_control/main.c new file mode 100644 index 0000000..48f9161 --- /dev/null +++ b/Nodes/LED_control/main.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015-2016 Ken Bannister. All rights reserved. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include +#include "msg.h" + +#include "net/gcoap.h" +#include "shell.h" + +#include "gcoap_example.h" + +#define MAIN_QUEUE_SIZE (4) +static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; + +int main(void) +{ + puts("CoAP example application"); + /* for the thread running the shell */ + msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE); + server_init(); + + /* start shell */ + puts("All up, running the shell now"); + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + + /* should never be reached */ + return 0; +} diff --git a/Nodes/LED_control/server.c b/Nodes/LED_control/server.c new file mode 100644 index 0000000..6a9e01c --- /dev/null +++ b/Nodes/LED_control/server.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015-2017 Ken Bannister. All rights reserved. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include +#include +#include +#include + +#include "fmt.h" +#include "net/gcoap.h" +#include "net/utils.h" +#include "od.h" + +#include "gcoap_example.h" + +#include "periph/gpio.h" +#include "board.h" + +static ssize_t _riot_board_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx); + +/* [TASK 2: add the prototype of your resource handler here] */ + +/* [TASK 2: declare the array of LEDs here] */ + +/* CoAP resources. Must be sorted by path (ASCII order). */ +static const coap_resource_t _resources[] = { + /* [TASK 2: register your CoAP resource here] */ + { "/riot/board", COAP_GET, _riot_board_handler, NULL }, +}; + +/* a gcoap listener is a collection of resources. Additionally we can specify + * custom functions to: + * - list our resources on the /.well-known/core + * - how our resources are matched on an incoming request (simple string + * comparison is the default) + */ +static gcoap_listener_t _listener = { + _resources, + ARRAY_SIZE(_resources), + GCOAP_SOCKET_TYPE_UDP, + NULL, + NULL, + NULL +}; + +void server_init(void) +{ + gcoap_register_listener(&_listener); + + /* [TASK 2: initialize the GPIOs here] */ +} + +/* [TASK 2: implement the LED handler here] */ + +/* + * Server callback for /riot/board. Accepts only GET. + * + * GET: Returns the name of the board in plain text + */ +static ssize_t _riot_board_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx) +{ + (void)ctx; + + /* initialize a new coap response */ + gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT); + + /* first we set all the options */ + /* set the format option to "plain text" */ + coap_opt_add_format(pdu, COAP_FORMAT_TEXT); + + /* finish the options sections */ + /* it is important to keep track of the amount of used bytes (resp_len) */ + size_t resp_len = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD); + + /* write the RIOT board name in the response buffer */ + if (pdu->payload_len >= strlen(RIOT_BOARD)) { + memcpy(pdu->payload, RIOT_BOARD, strlen(RIOT_BOARD)); + return resp_len + strlen(RIOT_BOARD); + } + else { + /* in this case we use a simple convenience function to create the + * response, it only allows to set a payload and a response code. */ + puts("gcoap_cli: msg buffer too small"); + return gcoap_response(pdu, buf, len, COAP_CODE_INTERNAL_SERVER_ERROR); + } +} diff --git a/Nodes/puzzle_weight/Makefile b/Nodes/puzzle_weight/Makefile index c062eaf..f3a77e6 100644 --- a/Nodes/puzzle_weight/Makefile +++ b/Nodes/puzzle_weight/Makefile @@ -2,7 +2,7 @@ APPLICATION = WeightPuzzle # If no BOARD is found in the environment, use this default: -BOARD ?= native +BOARD ?= pba-d-01-kw2x # This has to be the absolute path to the RIOT base directory: RIOTBASE ?= ../RIOT diff --git a/Nodes/puzzle_weight/README.md b/Nodes/puzzle_weight/README.md index b9eed9b..886e313 100644 --- a/Nodes/puzzle_weight/README.md +++ b/Nodes/puzzle_weight/README.md @@ -1,4 +1,10 @@ # Weight puzzle -something. something, weight, weight -(to be filled by Tristan) +This program measures the ouput of a load cell and converts it to a weight value. When the value is within the borders of a set goal for 2.5 seconds an LED will turn on, the puzzle is solved. The wanted value is 400g (water) + 22g weight of the bottle. When starting the puzzle the bottle cannot be on top of the weigh. + +Connection: +VDD - 3.3V +VCC - 5V +DAT - D6 +CLK - D2 +GND - GND diff --git a/Nodes/puzzle_weight/main.c b/Nodes/puzzle_weight/main.c index 5975312..36443b2 100644 --- a/Nodes/puzzle_weight/main.c +++ b/Nodes/puzzle_weight/main.c @@ -28,8 +28,8 @@ #include "puzzle_coap.h" -#define weight 55 /*wanted weight*/ -#define tolerance 0.1f /*tolerance of wanted weight*/ +#define weight 422 /*wanted weight*/ +#define tolerance 0.2f /*tolerance of wanted weight*/ #define STARTUP_DELAY (1U) #define MAIN_QUEUE_SIZE (4) @@ -48,7 +48,7 @@ static const puzzle_t puzzle = { .get_ready_handler = _ready, .set_ready_handler = _set_ready, .name = "Weight puzzle", - .resource_dir_uri = "coap://[fd00:dead:beef::1]", + .resource_dir_uri = "coap://[fd00:dead:beef::1]:5555", }; static bool _is_solved = false; @@ -59,7 +59,7 @@ void *meassure_weight(void *arg) (void) arg; int cnt = 0; /*counter*/ static hx711_t dev; - uint8_t times = 10; + uint8_t times = 5; puts("In thread"); /*initialize LED*/ @@ -81,7 +81,7 @@ void *meassure_weight(void *arg) while (1) { /* int32_t value = hx711_get_value(&dev, times); */ int32_t units = hx711_get_units(&dev, times); - + printf("%ld\n", units); /*check if measurement is within the borders*/ if ((units > weight - weight * tolerance) && (units < weight + weight * tolerance)) { cnt = cnt + 1;