初始化提交

This commit is contained in:
王立帮
2024-07-20 22:09:06 +08:00
commit c247dd07a6
6876 changed files with 2743096 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
/**
* @file BlynkApiLinux.h
* @author Volodymyr Shymanskyy
* @license This project is released under the MIT License (MIT)
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
* @date Mar 2015
* @brief
*
*/
#ifndef BlynkApiLinux_h
#define BlynkApiLinux_h
#include <Blynk/BlynkApi.h>
#ifndef BLYNK_INFO_DEVICE
#define BLYNK_INFO_DEVICE "Linux"
#endif
#ifdef BLYNK_NO_INFO
template<class Proto>
BLYNK_FORCE_INLINE
void BlynkApi<Proto>::sendInfo() {}
#else
template<class Proto>
BLYNK_FORCE_INLINE
void BlynkApi<Proto>::sendInfo()
{
static const char profile[] BLYNK_PROGMEM = "blnkinf\0"
BLYNK_PARAM_KV("ver" , BLYNK_VERSION)
BLYNK_PARAM_KV("h-beat" , BLYNK_TOSTRING(BLYNK_HEARTBEAT))
BLYNK_PARAM_KV("buff-in", BLYNK_TOSTRING(BLYNK_MAX_READBYTES))
#ifdef BLYNK_INFO_DEVICE
BLYNK_PARAM_KV("dev" , BLYNK_INFO_DEVICE)
#endif
#ifdef BLYNK_INFO_CPU
BLYNK_PARAM_KV("cpu" , BLYNK_INFO_CPU)
#endif
#ifdef BLYNK_INFO_CONNECTION
BLYNK_PARAM_KV("con" , BLYNK_INFO_CONNECTION)
#endif
#ifdef BOARD_FIRMWARE_VERSION
BLYNK_PARAM_KV("fw" , BOARD_FIRMWARE_VERSION)
#endif
BLYNK_PARAM_KV("build" , __DATE__ " " __TIME__)
"\0"
;
const size_t profile_len = sizeof(profile)-8-2;
char mem_dyn[64];
BlynkParam profile_dyn(mem_dyn, 0, sizeof(mem_dyn));
profile_dyn.add_key("conn", "Socket");
#ifdef BOARD_TEMPLATE_ID
profile_dyn.add_key("tmpl", BOARD_TEMPLATE_ID);
#endif
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_INTERNAL, 0, profile+8, profile_len, profile_dyn.getBuffer(), profile_dyn.getLength());
return;
}
#endif
template<class Proto>
BLYNK_FORCE_INLINE
void BlynkApi<Proto>::processCmd(const void* buff, size_t len)
{
BlynkParam param((void*)buff, len);
BlynkParam::iterator it = param.begin();
if (it >= param.end())
return;
const char* cmd = it.asStr();
uint16_t cmd16;
memcpy(&cmd16, cmd, sizeof(cmd16));
if (++it >= param.end())
return;
const uint8_t pin = it.asInt();
switch(cmd16) {
#ifndef BLYNK_NO_BUILTIN
case BLYNK_HW_PM: {
while (it < param.end()) {
++it;
#ifdef BLYNK_DEBUG
BLYNK_LOG4(BLYNK_F("Invalid pin "), pin, BLYNK_F(" mode "), it.asStr());
#endif
++it;
}
} break;
case BLYNK_HW_DR: {
char mem[16];
BlynkParam rsp(mem, 0, sizeof(mem));
rsp.add("dw");
rsp.add(pin);
rsp.add(0); // TODO
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, rsp.getBuffer(), rsp.getLength()-1);
} break;
case BLYNK_HW_DW: {
// Should be 1 parameter (value)
if (++it >= param.end())
return;
// TODO: digitalWrite(pin, it.asInt() ? HIGH : LOW);
} break;
case BLYNK_HW_AW: {
// Should be 1 parameter (value)
if (++it >= param.end())
return;
// TODO: analogWrite(pin, it.asInt());
} break;
#endif
case BLYNK_HW_VR: {
BlynkReq req = { pin };
WidgetReadHandler handler = GetReadHandler(pin);
if (handler && (handler != BlynkWidgetRead)) {
handler(req);
} else {
BlynkWidgetReadDefault(req);
}
} break;
case BLYNK_HW_VW: {
++it;
char* start = (char*)it.asStr();
BlynkParam param2(start, len - (start - (char*)buff));
BlynkReq req = { pin };
WidgetWriteHandler handler = GetWriteHandler(pin);
if (handler && (handler != BlynkWidgetWrite)) {
handler(req, param2);
} else {
BlynkWidgetWriteDefault(req, param2);
}
} break;
default:
BLYNK_LOG2(BLYNK_F("Invalid HW cmd: "), cmd);
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_RESPONSE, static_cast<Proto*>(this)->msgIdOutOverride, NULL, BLYNK_ILLEGAL_COMMAND);
}
}
#endif

View File

@@ -0,0 +1,177 @@
/**
* @file BlynkApiWiringPi.h
* @author Volodymyr Shymanskyy
* @license This project is released under the MIT License (MIT)
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
* @date Mar 2015
* @brief
*
*/
#ifndef BlynkApiWiringPi_h
#define BlynkApiWiringPi_h
#include <Blynk/BlynkApi.h>
#ifndef BLYNK_INFO_DEVICE
#define BLYNK_INFO_DEVICE "Raspberry"
#endif
#ifdef BLYNK_NO_INFO
template<class Proto>
BLYNK_FORCE_INLINE
void BlynkApi<Proto>::sendInfo() {}
#else
template<class Proto>
BLYNK_FORCE_INLINE
void BlynkApi<Proto>::sendInfo()
{
static const char profile[] BLYNK_PROGMEM = "blnkinf\0"
BLYNK_PARAM_KV("ver" , BLYNK_VERSION)
BLYNK_PARAM_KV("h-beat" , BLYNK_TOSTRING(BLYNK_HEARTBEAT))
BLYNK_PARAM_KV("buff-in", BLYNK_TOSTRING(BLYNK_MAX_READBYTES))
#ifdef BLYNK_INFO_DEVICE
BLYNK_PARAM_KV("dev" , BLYNK_INFO_DEVICE)
#endif
#ifdef BLYNK_INFO_CPU
BLYNK_PARAM_KV("cpu" , BLYNK_INFO_CPU)
#endif
#ifdef BLYNK_INFO_CONNECTION
BLYNK_PARAM_KV("con" , BLYNK_INFO_CONNECTION)
#endif
#ifdef BOARD_FIRMWARE_VERSION
BLYNK_PARAM_KV("fw" , BOARD_FIRMWARE_VERSION)
#endif
BLYNK_PARAM_KV("build" , __DATE__ " " __TIME__)
"\0"
;
const size_t profile_len = sizeof(profile)-8-2;
char mem_dyn[64];
BlynkParam profile_dyn(mem_dyn, 0, sizeof(mem_dyn));
profile_dyn.add_key("conn", "Socket");
#ifdef BOARD_TEMPLATE_ID
profile_dyn.add_key("tmpl", BOARD_TEMPLATE_ID);
#endif
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_INTERNAL, 0, profile+8, profile_len, profile_dyn.getBuffer(), profile_dyn.getLength());
return;
}
#endif
// Check if analog pins can be referenced by name on this device
#if defined(analogInputToDigitalPin)
#define BLYNK_DECODE_PIN(it) (((it).asStr()[0] == 'A') ? analogInputToDigitalPin(atoi((it).asStr()+1)) : (it).asInt())
#else
#define BLYNK_DECODE_PIN(it) ((it).asInt())
#if defined(BLYNK_DEBUG_ALL)
#pragma message "analogInputToDigitalPin not defined"
#endif
#endif
template<class Proto>
BLYNK_FORCE_INLINE
void BlynkApi<Proto>::processCmd(const void* buff, size_t len)
{
BlynkParam param((void*)buff, len);
BlynkParam::iterator it = param.begin();
if (it >= param.end())
return;
const char* cmd = it.asStr();
uint16_t cmd16;
memcpy(&cmd16, cmd, sizeof(cmd16));
if (++it >= param.end())
return;
uint8_t pin = BLYNK_DECODE_PIN(it);
switch(cmd16) {
#ifndef BLYNK_NO_BUILTIN
case BLYNK_HW_PM: {
while (it < param.end()) {
pin = BLYNK_DECODE_PIN(it);
++it;
if (!strcmp(it.asStr(), "in")) {
pinMode(pin, INPUT);
pullUpDnControl(pin, PUD_OFF);
} else if (!strcmp(it.asStr(), "out")) {
pinMode(pin, OUTPUT);
} else if (!strcmp(it.asStr(), "pu")) {
pinMode(pin, INPUT);
pullUpDnControl(pin, PUD_UP);
} else if (!strcmp(it.asStr(), "pd")) {
pinMode(pin, INPUT);
pullUpDnControl(pin, PUD_DOWN);
} else if (!strcmp(it.asStr(), "pwm")) {
pinMode(pin, PWM_OUTPUT);
} else {
#ifdef BLYNK_DEBUG
BLYNK_LOG4(BLYNK_F("Invalid pin "), pin, BLYNK_F(" mode "), it.asStr());
#endif
}
++it;
}
} break;
case BLYNK_HW_DR: {
char mem[16];
BlynkParam rsp(mem, 0, sizeof(mem));
rsp.add("dw");
rsp.add(pin);
rsp.add(digitalRead(pin));
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, rsp.getBuffer(), rsp.getLength()-1);
} break;
case BLYNK_HW_DW: {
// Should be 1 parameter (value)
if (++it >= param.end())
return;
pinMode(pin, OUTPUT);
digitalWrite(pin, it.asInt() ? HIGH : LOW);
} break;
case BLYNK_HW_AW: {
// Should be 1 parameter (value)
if (++it >= param.end())
return;
pinMode(pin, PWM_OUTPUT);
pwmWrite(pin, it.asInt());
} break;
#endif
case BLYNK_HW_VR: {
BlynkReq req = { pin };
WidgetReadHandler handler = GetReadHandler(pin);
if (handler && (handler != BlynkWidgetRead)) {
handler(req);
} else {
BlynkWidgetReadDefault(req);
}
} break;
case BLYNK_HW_VW: {
++it;
char* start = (char*)it.asStr();
BlynkParam param2(start, len - (start - (char*)buff));
BlynkReq req = { pin };
WidgetWriteHandler handler = GetWriteHandler(pin);
if (handler && (handler != BlynkWidgetWrite)) {
handler(req, param2);
} else {
BlynkWidgetWriteDefault(req, param2);
}
} break;
default:
BLYNK_LOG2(BLYNK_F("Invalid HW cmd: "), cmd);
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_RESPONSE, static_cast<Proto*>(this)->msgIdOutOverride, NULL, BLYNK_ILLEGAL_COMMAND);
}
}
#endif

View File

@@ -0,0 +1,47 @@
#include <getopt.h>
#include <Blynk/BlynkDebug.h>
static
void parse_options(int argc, char* argv[],
const char*& auth,
const char*& serv,
uint16_t& port)
{
static struct option long_options[] = {
{"token", required_argument, 0, 't'},
{"server", required_argument, 0, 's'},
{"port", required_argument, 0, 'p'},
{0, 0, 0, 0}
};
// Set default values
auth = NULL;
serv = BLYNK_DEFAULT_DOMAIN;
port = BLYNK_DEFAULT_PORT;
const char* usage =
"Usage: blynk [options]\n"
"\n"
"Options:\n"
" -t auth, --token=auth Your auth token\n"
" -s addr, --server=addr Server name (default: " BLYNK_DEFAULT_DOMAIN ")\n"
" -p num, --port=num Server port (default: " BLYNK_TOSTRING(BLYNK_DEFAULT_PORT) ")\n"
"\n";
int rez;
while (-1 != (rez = getopt_long(argc, argv,"t:s:p:", long_options, NULL))) {
switch (rez) {
case 't': auth = optarg; break;
case 's': serv = optarg; break;
case 'p': port = atoi(optarg); break;
default : printf(usage); exit(1);
};
};
// Check mandatory options
if (!auth) {
printf(usage);
exit(1);
}
}

View File

@@ -0,0 +1,157 @@
/**
* @file BlynkSocket.h
* @author Volodymyr Shymanskyy
* @license This project is released under the MIT License (MIT)
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
* @date Mar 2015
* @brief
*/
#ifndef BlynkSocket_h
#define BlynkSocket_h
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <Blynk/BlynkProtocol.h>
class BlynkTransportSocket
{
public:
BlynkTransportSocket()
: sockfd(-1), domain(NULL), port(0)
{}
void begin(const char* h, uint16_t p) {
this->domain = h;
this->port = p;
}
bool connect()
{
BLYNK_LOG4(BLYNK_F("Connecting to "), domain, ':', port);
struct addrinfo hints;
struct addrinfo *res = NULL; // will point to the results
memset(&hints, 0, sizeof hints); // make sure the struct is empty
hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
// get ready to connect
char port_str[8];
snprintf(port_str, sizeof(port_str), "%u", port);
getaddrinfo(domain, port_str, &hints, &res);
if (res == NULL) {
BLYNK_LOG1(BLYNK_F("Cannot get addr info"));
return false;
}
if ((sockfd = ::socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
{
BLYNK_LOG1(BLYNK_F("Can't create socket"));
return false;
}
if (::connect(sockfd, res->ai_addr, res->ai_addrlen) < 0)
{
BLYNK_LOG2(BLYNK_F("Can't connect to "), domain);
return false;
}
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 1000;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
int one = 1;
setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
freeaddrinfo(res); // TODO: Leak here
return true;
}
void disconnect()
{
if (sockfd != -1) {
while (::close(sockfd) < 0) {
usleep(10000);
}
sockfd = -1;
}
}
size_t read(void* buf, size_t len) {
ssize_t rlen = ::read(sockfd, buf, len);
if (rlen == -1) {
//BLYNK_LOG4("Read error ", errno, ": ", strerror(errno));
if (errno == ETIMEDOUT || errno == EWOULDBLOCK || errno == EAGAIN) {
return 0;
}
disconnect();
return -1;
}
return rlen;
}
size_t write(const void* buf, size_t len) {
return ::write(sockfd, buf, len);
}
bool connected() {
return sockfd >= 0;
}
int available() {
if (!connected()) {
return 0;
}
int count = 0;
if (0 == ioctl(sockfd, FIONREAD, &count)) {
if (!count) {
usleep(10000); // not to stall CPU with 100% load
}
return count;
}
return 0;
}
protected:
int sockfd;
const char* domain;
uint16_t port;
};
class BlynkSocket
: public BlynkProtocol<BlynkTransportSocket>
{
typedef BlynkProtocol<BlynkTransportSocket> Base;
public:
BlynkSocket(BlynkTransportSocket& transp)
: Base(transp)
{}
void begin(const char* auth,
const char* domain = BLYNK_DEFAULT_DOMAIN,
uint16_t port = BLYNK_DEFAULT_PORT)
{
Base::begin(auth);
this->conn.begin(domain, port);
}
};
#endif

View File

@@ -0,0 +1,70 @@
#
# To build on RaspberryPi:
# 1. Install WiringPi: http://wiringpi.com/download-and-install/
# 2. Run:
# make target=raspberry
# sudo blynk --token=YourAuthToken
#
CC ?= gcc
CXX ?= g++
CXXFLAGS += -I ../src/ -I ./ -DLINUX
LDFLAGS += -lrt -lpthread
ifeq ($(build),debug)
CXXFLAGS += -c -g2 -O0 \
-Wall -Weffc++ \
-Wextra -Wcast-align \
-Wchar-subscripts -Wcomment -Wconversion \
-Wdisabled-optimization \
-Wfloat-equal -Wformat -Wformat=2 \
-Wformat-nonliteral -Wformat-security \
-Wformat-y2k \
-Wimplicit -Wimport -Winit-self -Winline \
-Winvalid-pch \
-Wunsafe-loop-optimizations -Wlong-long -Wmissing-braces \
-Wmissing-field-initializers -Wmissing-format-attribute \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked -Wparentheses -Wpointer-arith \
-Wredundant-decls -Wreturn-type \
-Wsequence-point -Wshadow -Wsign-compare -Wstack-protector \
-Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch -Wswitch-default \
-Wswitch-enum -Wtrigraphs -Wuninitialized \
-Wunknown-pragmas -Wunreachable-code -Wunused \
-Wunused-function -Wunused-label \
-Wunused-value -Wunused-variable \
-Wvolatile-register-var -Wwrite-strings
# Disable some warnings
CXXFLAGS += -Wno-variadic-macros -Wno-unused-parameter -Wno-vla
# Uncomment this to get pedantic warnings:
#CXXFLAGS += -pedantic -Wvariadic-macros -Wunused-parameter -Waggregate-return -Wcast-qual -Wpadded
else
CXXFLAGS += -c -O3 -w
LDFLAGS += -s
endif
ifeq ($(target),raspberry)
CXXFLAGS += -DRASPBERRY
LDFLAGS += -lwiringPi
endif
SOURCES=main.cpp \
../src/utility/BlynkDebug.cpp \
../src/utility/BlynkHandlers.cpp \
../src/utility/BlynkTimer.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=blynk
all: $(SOURCES) $(EXECUTABLE)
clean:
-rm $(OBJECTS) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CXX) $(OBJECTS) $(LDFLAGS) -o $@
.cpp.o:
$(CXX) $(CXXFLAGS) $< -o $@

View File

@@ -0,0 +1,24 @@
# Linux Quick Start Guide (Ubuntu, Raspberry Pi, ...)
0. Connect your Raspberry Pi to the internet and open it's console. ^_^
1. Install WiringPi:
http://wiringpi.com/download-and-install/
2. Download and build Blynk:
```bash
$ git clone https://github.com/blynkkk/blynk-library.git
$ cd blynk-library/linux
$ make clean all target=raspberry
```
3. Run Blynk:
```bash
$ sudo ./blynk --token=YourAuthToken
```
We have also provided a build script, you can try just running (inside of the "linux" directory):
```bash
$ ./build.sh raspberry
```

View File

@@ -0,0 +1,24 @@
#!/bin/bash
case "$1" in
raspberry)
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential git-core
git clone git://git.drogon.net/wiringPi
cd wiringPi
git pull origin
./build
gpio -v
cd ..
make clean all target=raspberry
exit 0
;;
linux)
make clean all
exit 0
;;
esac
echo "Please specify platform: raspberry, linux"
exit 1

View File

@@ -0,0 +1,61 @@
/**
* @file main.cpp
* @author Volodymyr Shymanskyy
* @license This project is released under the MIT License (MIT)
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
* @date Mar 2015
* @brief
*/
//#define BLYNK_DEBUG
#define BLYNK_PRINT stdout
#ifdef RASPBERRY
#include <BlynkApiWiringPi.h>
#else
#include <BlynkApiLinux.h>
#endif
#include <BlynkSocket.h>
#include <BlynkOptionsParser.h>
static BlynkTransportSocket _blynkTransport;
BlynkSocket Blynk(_blynkTransport);
static const char *auth, *serv;
static uint16_t port;
#include <BlynkWidgets.h>
BlynkTimer tmr;
BLYNK_WRITE(V1)
{
printf("Got a value: %s\n", param[0].asStr());
}
void setup()
{
Blynk.begin(auth, serv, port);
tmr.setInterval(1000, [](){
Blynk.virtualWrite(V0, BlynkMillis()/1000);
});
}
void loop()
{
Blynk.run();
tmr.run();
}
int main(int argc, char* argv[])
{
parse_options(argc, argv, auth, serv, port);
setup();
while(true) {
loop();
}
return 0;
}