2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
16 * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
17 * Copyright (C) 2021 Nuno Goncalves <nunojpg@gmail.com>
23 #include <libubox/ulog.h>
24 #include <libubox/ustream.h>
25 #include <libubox/utils.h>
26 #include <libubox/uloop.h>
29 static struct ustream_fd stream
;
30 static struct ubus_auto_conn conn
;
31 static struct blob_buf b
;
51 const char *from
= read
+ 5;
53 battery
.soc
= strtoul(from
, &to
, 10);
57 battery
.temperature
= strtoul(from
, &to
, 10) / 10.0f
;
60 if (to
[0] != ',' || (to
[1] != '0' && to
[1] != '1') || to
[2] != ',')
62 battery
.charging
= to
[1] == '1';
64 battery
.cycles
= strtoul(from
, &to
, 10);
71 consume(struct ustream
*s
, char **a
)
73 char *eol
= strstr(*a
, "\n");
80 battery
.set
= process(*a
);
82 ULOG_ERR("failed to parse message from serial: %s", *a
);
84 ustream_consume(s
, eol
- *a
);
91 msg_cb(struct ustream
*s
, int bytes
)
94 char *a
= ustream_get_read_buf(s
, &len
);
96 while (!consume(s
, &a
))
101 notify_cb(struct ustream
*s
)
106 ULOG_ERR("tty error, shutting down\n");
111 serial_open(char *dev
)
113 const int tty
= open(dev
, O_RDWR
| O_NOCTTY
| O_NONBLOCK
);
116 ULOG_ERR("%s: device open failed: %s\n", dev
, strerror(errno
));
120 struct termios config
;
121 tcgetattr(tty
, &config
);
123 cfsetispeed(&config
, B9600
);
124 cfsetospeed(&config
, B9600
);
125 tcsetattr(tty
, TCSANOW
, &config
);
127 stream
.stream
.string_data
= true;
128 stream
.stream
.notify_read
= msg_cb
;
129 stream
.stream
.notify_state
= notify_cb
;
131 ustream_fd_init(&stream
, tty
);
133 tcflush(tty
, TCIFLUSH
);
138 static struct uloop_timeout serial_query_timer
;
140 serial_query_handler(struct uloop_timeout
*timeout
)
142 const char cmd
[] = "{ \"mcu_status\": \"1\" }\n";
143 const unsigned cmd_len
= sizeof(cmd
) - 1;
144 ustream_write(&stream
.stream
, cmd
, cmd_len
, false);
145 uloop_timeout_set(&serial_query_timer
, 3000); // timeout in 3 sec
146 uloop_timeout_add(timeout
);
150 battery_info(struct ubus_context
*ctx
, struct ubus_object
*obj
,
151 struct ubus_request_data
*req
, const char *method
,
152 struct blob_attr
*msg
)
154 blob_buf_init(&b
, 0);
158 blobmsg_add_u8(&b
, "error", 1);
162 blobmsg_add_u16(&b
, "soc", battery
.soc
);
163 blobmsg_add_u8(&b
, "charging", battery
.charging
);
164 blobmsg_add_double(&b
, "temperature", battery
.temperature
);
165 blobmsg_add_u16(&b
, "cycles", battery
.cycles
);
167 ubus_send_reply(ctx
, req
, b
.head
);
169 return UBUS_STATUS_OK
;
172 static const struct ubus_method battery_methods
[] = {
173 UBUS_METHOD_NOARG("info", battery_info
),
176 static struct ubus_object_type battery_object_type
=
177 UBUS_OBJECT_TYPE("battery", battery_methods
);
179 static struct ubus_object battery_object
= {
181 .type
= &battery_object_type
,
182 .methods
= battery_methods
,
183 .n_methods
= ARRAY_SIZE(battery_methods
),
187 ubus_connect_handler(struct ubus_context
*ctx
)
191 ret
= ubus_add_object(ctx
, &battery_object
);
193 fprintf(stderr
, "Failed to add object: %s\n", ubus_strerror(ret
));
197 main(int argc
, char **argv
)
202 conn
.cb
= ubus_connect_handler
;
203 ubus_auto_connect(&conn
);
205 if (serial_open("/dev/ttyUSB0") < 0)
208 serial_query_timer
.cb
= serial_query_handler
;
209 serial_query_handler(&serial_query_timer
);