migration
This commit is contained in:
+11
-11
@@ -1,11 +1,11 @@
|
|||||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||||
# in this exact order for cmake to work correctly
|
# in this exact order for cmake to work correctly
|
||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
project(can2http)
|
project(can2http)
|
||||||
|
|
||||||
# Create a SPIFFS image from the contents of the 'csv' FLASH_IN_PROJECT indicates that
|
# Create a SPIFFS image from the contents of the 'csv' FLASH_IN_PROJECT indicates that
|
||||||
# the generated image should be flashed when the entire project is flashed to
|
# the generated image should be flashed when the entire project is flashed to
|
||||||
# the target with 'idf.py -p PORT flash
|
# the target with 'idf.py -p PORT flash
|
||||||
spiffs_create_partition_image(storage csv FLASH_IN_PROJECT)
|
spiffs_create_partition_image(storage csv FLASH_IN_PROJECT)
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2024 PrincessPi3 and nopnop2002
|
Copyright (c) 2024 PrincessPi3 and nopnop2002
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|||||||
@@ -1,289 +1,289 @@
|
|||||||
# Sillyfilly-CAN
|
# Sillyfilly-CAN
|
||||||
A fork of [esp-idf-can2http](https://github.com/nopnop2002/esp-idf-can2http)
|
A fork of [esp-idf-can2http](https://github.com/nopnop2002/esp-idf-can2http)
|
||||||
|
|
||||||
A CAN bus tool built for the esp32. It has a builtin web interface and works with nearly any CAN transceiver like the [N65HVD230](https://www.amazon.com/SN65HVD230-CAN-Board-Communication-Development/dp/B00KM6XMXO/) or the [TJA1050](https://www.amazon.com/Comimark-Transceiver-TJA1050-Controller-Schnittstelle/dp/B07W4VZ2F2/)
|
A CAN bus tool built for the esp32. It has a builtin web interface and works with nearly any CAN transceiver like the [N65HVD230](https://www.amazon.com/SN65HVD230-CAN-Board-Communication-Development/dp/B00KM6XMXO/) or the [TJA1050](https://www.amazon.com/Comimark-Transceiver-TJA1050-Controller-Schnittstelle/dp/B07W4VZ2F2/)
|
||||||
|
|
||||||
## Hardware needed
|
## Hardware needed
|
||||||
* esp32(-X) (My favorite esp32)[https://www.amazon.com/Espressif-ESP32-S3-DevKitC-1-N32R8V-Development-Board/dp/B09R4GSDJM]
|
* esp32(-X) (My favorite esp32)[https://www.amazon.com/Espressif-ESP32-S3-DevKitC-1-N32R8V-Development-Board/dp/B09R4GSDJM]
|
||||||
* CAN transceiver like the [N65HVD230](https://www.amazon.com/SN65HVD230-CAN-Board-Communication-Development/dp/B00KM6XMXO/) or the [TJA1050](https://www.amazon.com/Comimark-Transceiver-TJA1050-Controller-Schnittstelle/dp/B07W4VZ2F2/)
|
* CAN transceiver like the [N65HVD230](https://www.amazon.com/SN65HVD230-CAN-Board-Communication-Development/dp/B00KM6XMXO/) or the [TJA1050](https://www.amazon.com/Comimark-Transceiver-TJA1050-Controller-Schnittstelle/dp/B07W4VZ2F2/)
|
||||||
some jumper wires
|
some jumper wires
|
||||||
* Jumper wires
|
* Jumper wires
|
||||||
|
|
||||||
## Optional
|
## Optional
|
||||||
* [ODB2 pigtail](https://www.amazon.com/iKKEGOL-Connector-Diagnostic-Extension-Pigtail/dp/B0828YHWFG/)
|
* [ODB2 pigtail](https://www.amazon.com/iKKEGOL-Connector-Diagnostic-Extension-Pigtail/dp/B0828YHWFG/)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
1) install [esp-idf](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/index.html#installation) if not installed on your computer already
|
1) install [esp-idf](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/index.html#installation) if not installed on your computer already
|
||||||
2) open esp-idf terminal
|
2) open esp-idf terminal
|
||||||
3) plug in your esp32 to computer via USB cable
|
3) plug in your esp32 to computer via USB cable
|
||||||
4) Run these commands:
|
4) Run these commands:
|
||||||
```
|
```
|
||||||
git clone https://github.com/PrincessPi3/Sillyfilly-CAN.git
|
git clone https://github.com/PrincessPi3/Sillyfilly-CAN.git
|
||||||
cd Sillyfilly-CAN
|
cd Sillyfilly-CAN
|
||||||
idf.py set-target esp32s3 # example idf.py set-target <your_esp32_ type>
|
idf.py set-target esp32s3 # example idf.py set-target <your_esp32_ type>
|
||||||
idf.py menuconfig
|
idf.py menuconfig
|
||||||
```
|
```
|
||||||
5) Under "Sillyfilly-CAN Configuration" set your settings like wifi and CRX and CTX pins.
|
5) Under "Sillyfilly-CAN Configuration" set your settings like wifi and CRX and CTX pins.
|
||||||
6) Wire transceiver to the pins: CRX->RX, CTX-TX, GND->GND
|
6) Wire transceiver to the pins: CRX->RX, CTX-TX, GND->GND
|
||||||
7) run this command
|
7) run this command
|
||||||
```idf.py flash monitor # ctrl+] to exit monitor```
|
```idf.py flash monitor # ctrl+] to exit monitor```
|
||||||
<your_esp32_type> can be one of 'esp32', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'
|
<your_esp32_type> can be one of 'esp32', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'
|
||||||
|
|
||||||
# Original README.md
|
# Original README.md
|
||||||
# esp-idf-can2http
|
# esp-idf-can2http
|
||||||
CANbus to http bridge using esp32.
|
CANbus to http bridge using esp32.
|
||||||
It's purpose is to be a bridge between a CAN-Bus and a HTTP-Server.
|
It's purpose is to be a bridge between a CAN-Bus and a HTTP-Server.
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
# Software requirement
|
# Software requirement
|
||||||
ESP-IDF V4.4/V5.x.
|
ESP-IDF V4.4/V5.x.
|
||||||
ESP-IDF V5.1 is required when using ESP32C6.
|
ESP-IDF V5.1 is required when using ESP32C6.
|
||||||
|
|
||||||
# Hardware requirements
|
# Hardware requirements
|
||||||
- SN65HVD23x CAN-BUS Transceiver
|
- SN65HVD23x CAN-BUS Transceiver
|
||||||
SN65HVD23x series has 230/231/232.
|
SN65HVD23x series has 230/231/232.
|
||||||
They differ in standby/sleep mode functionality.
|
They differ in standby/sleep mode functionality.
|
||||||
Other features are the same.
|
Other features are the same.
|
||||||
|
|
||||||
- Termination resistance
|
- Termination resistance
|
||||||
I used 150 ohms.
|
I used 150 ohms.
|
||||||
|
|
||||||
# Wireing
|
# Wireing
|
||||||
|SN65HVD23x||ESP32|ESP32-S2/S3|ESP32-C3/C6||
|
|SN65HVD23x||ESP32|ESP32-S2/S3|ESP32-C3/C6||
|
||||||
|:-:|:-:|:-:|:-:|:-:|:-:|
|
|:-:|:-:|:-:|:-:|:-:|:-:|
|
||||||
|D(CTX)|--|GPIO21|GPIO17|GPIO0|(*1)|
|
|D(CTX)|--|GPIO21|GPIO17|GPIO0|(*1)|
|
||||||
|GND|--|GND|GND|GND||
|
|GND|--|GND|GND|GND||
|
||||||
|Vcc|--|3.3V|3.3V|3.3V||
|
|Vcc|--|3.3V|3.3V|3.3V||
|
||||||
|R(CRX)|--|GPIO22|GPIO18|GPIO1|(*1)|
|
|R(CRX)|--|GPIO22|GPIO18|GPIO1|(*1)|
|
||||||
|Vref|--|N/C|N/C|N/C||
|
|Vref|--|N/C|N/C|N/C||
|
||||||
|CANL|--||||To CAN Bus|
|
|CANL|--||||To CAN Bus|
|
||||||
|CANH|--||||To CAN Bus|
|
|CANH|--||||To CAN Bus|
|
||||||
|RS|--|GND|GND|GND|(*2)|
|
|RS|--|GND|GND|GND|(*2)|
|
||||||
|
|
||||||
(*1) You can change using menuconfig. But it may not work with other GPIOs.
|
(*1) You can change using menuconfig. But it may not work with other GPIOs.
|
||||||
|
|
||||||
(*2) N/C for SN65HVD232
|
(*2) N/C for SN65HVD232
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Test Circuit
|
# Test Circuit
|
||||||
```
|
```
|
||||||
+-----------+ +-----------+ +-----------+
|
+-----------+ +-----------+ +-----------+
|
||||||
| Atmega328 | | Atmega328 | | ESP32 |
|
| Atmega328 | | Atmega328 | | ESP32 |
|
||||||
| | | | | |
|
| | | | | |
|
||||||
| Transmit | | Receive | | 21 22 |
|
| Transmit | | Receive | | 21 22 |
|
||||||
+-----------+ +-----------+ +-----------+
|
+-----------+ +-----------+ +-----------+
|
||||||
| | | | | |
|
| | | | | |
|
||||||
+-----------+ +-----------+ | |
|
+-----------+ +-----------+ | |
|
||||||
| | | | | |
|
| | | | | |
|
||||||
| MCP2515 | | MCP2515 | | |
|
| MCP2515 | | MCP2515 | | |
|
||||||
| | | | | |
|
| | | | | |
|
||||||
+-----------+ +-----------+ | |
|
+-----------+ +-----------+ | |
|
||||||
| | | | | |
|
| | | | | |
|
||||||
+-----------+ +-----------+ +-----------+
|
+-----------+ +-----------+ +-----------+
|
||||||
| | | | | D R |
|
| | | | | D R |
|
||||||
| MCP2551 | | MCP2551 | | VP230 |
|
| MCP2551 | | MCP2551 | | VP230 |
|
||||||
| H L | | H L | | H L |
|
| H L | | H L | | H L |
|
||||||
+-----------+ +-----------+ +-----------+
|
+-----------+ +-----------+ +-----------+
|
||||||
| | | | | |
|
| | | | | |
|
||||||
+--^^^--+ | | +--^^^--+
|
+--^^^--+ | | +--^^^--+
|
||||||
| R1 | | | | R2 |
|
| R1 | | | | R2 |
|
||||||
|---+-------|-------+-------|-------+-------|---| BackBorn H
|
|---+-------|-------+-------|-------+-------|---| BackBorn H
|
||||||
| | |
|
| | |
|
||||||
| | |
|
| | |
|
||||||
| | |
|
| | |
|
||||||
|-----------+---------------+---------------+---| BackBorn L
|
|-----------+---------------+---------------+---| BackBorn L
|
||||||
|
|
||||||
+--^^^--+:Terminaror register
|
+--^^^--+:Terminaror register
|
||||||
R1:120 ohms
|
R1:120 ohms
|
||||||
R2:150 ohms(Not working at 120 ohms)
|
R2:150 ohms(Not working at 120 ohms)
|
||||||
```
|
```
|
||||||
|
|
||||||
__NOTE__
|
__NOTE__
|
||||||
3V CAN Trasnceviers like VP230 are fully interoperable with 5V CAN trasnceviers like MCP2551.
|
3V CAN Trasnceviers like VP230 are fully interoperable with 5V CAN trasnceviers like MCP2551.
|
||||||
Check [here](http://www.ti.com/lit/an/slla337/slla337.pdf).
|
Check [here](http://www.ti.com/lit/an/slla337/slla337.pdf).
|
||||||
|
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
```
|
```
|
||||||
git clone https://github.com/nopnop2002/esp-idf-can2http
|
git clone https://github.com/nopnop2002/esp-idf-can2http
|
||||||
cd esp-idf-can2http
|
cd esp-idf-can2http
|
||||||
idf.py set-target {esp32/esp32s2/esp32s3/esp32c3/esp32c6}
|
idf.py set-target {esp32/esp32s2/esp32s3/esp32c3/esp32c6}
|
||||||
idf.py menuconfig
|
idf.py menuconfig
|
||||||
idf.py flash
|
idf.py flash
|
||||||
```
|
```
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
## CAN Setting
|
## CAN Setting
|
||||||

|

|
||||||
|
|
||||||
## WiFi Setting
|
## WiFi Setting
|
||||||

|

|
||||||
|
|
||||||
You can use static IP.
|
You can use static IP.
|
||||||

|

|
||||||
|
|
||||||
You can connect using mDNS.
|
You can connect using mDNS.
|
||||||

|

|
||||||
|
|
||||||
## External HTTP Server Setting
|
## External HTTP Server Setting
|
||||||
The External HTTP Server receives CAN Bus received data.
|
The External HTTP Server receives CAN Bus received data.
|
||||||

|

|
||||||
|
|
||||||
__Note__
|
__Note__
|
||||||
The Built-in HTTP Server receives CAN Bus transmittion data.
|
The Built-in HTTP Server receives CAN Bus transmittion data.
|
||||||
|
|
||||||
# Definition from CANbus to HTTP
|
# Definition from CANbus to HTTP
|
||||||
When CANbus data is received, it is sent by HTTP POST according to csv/can2http.csv.
|
When CANbus data is received, it is sent by HTTP POST according to csv/can2http.csv.
|
||||||
The file can2http.csv has three columns.
|
The file can2http.csv has three columns.
|
||||||
In the first column you need to specify the CAN Frame type.
|
In the first column you need to specify the CAN Frame type.
|
||||||
The CAN frame type is either S(Standard frame) or E(Extended frame).
|
The CAN frame type is either S(Standard frame) or E(Extended frame).
|
||||||
In the second column you have to specify the CAN-ID as a __hexdecimal number__.
|
In the second column you have to specify the CAN-ID as a __hexdecimal number__.
|
||||||
In the last column you have to specify the HTTP-POST-Path of external HTTP server.
|
In the last column you have to specify the HTTP-POST-Path of external HTTP server.
|
||||||
Each CAN-ID is allowed to appear only once in the whole file.
|
Each CAN-ID is allowed to appear only once in the whole file.
|
||||||
|
|
||||||
```
|
```
|
||||||
S,101,/post
|
S,101,/post
|
||||||
E,101,/post
|
E,101,/post
|
||||||
S,103,/post
|
S,103,/post
|
||||||
E,103,/post
|
E,103,/post
|
||||||
```
|
```
|
||||||
|
|
||||||
When a CAN frame with ID 0x101 is received, POST with the 'canid':257.
|
When a CAN frame with ID 0x101 is received, POST with the 'canid':257.
|
||||||
When a CAN frame with ID 0x103 is received, POST with the 'canid':259.
|
When a CAN frame with ID 0x103 is received, POST with the 'canid':259.
|
||||||
|
|
||||||
POST Parameter Example:
|
POST Parameter Example:
|
||||||
CAN-ID is a decimal number, not a hexadecimal number.
|
CAN-ID is a decimal number, not a hexadecimal number.
|
||||||
|
|
||||||
```
|
```
|
||||||
{"canid":257, "frame": "standard", "data": [16, 17, 18]}
|
{"canid":257, "frame": "standard", "data": [16, 17, 18]}
|
||||||
{"canid":257, "frame": "extended", "data": [16, 17, 18]}
|
{"canid":257, "frame": "extended", "data": [16, 17, 18]}
|
||||||
{"canid":259, "frame": "standard", "data": [16, 17, 18]}
|
{"canid":259, "frame": "standard", "data": [16, 17, 18]}
|
||||||
{"canid":259, "frame": "extended", "data": [16, 17, 18]}
|
{"canid":259, "frame": "extended", "data": [16, 17, 18]}
|
||||||
```
|
```
|
||||||
|
|
||||||
__CAN messages not registered in csv/can2http.csv are discarded and not POSTed to HTTP.__
|
__CAN messages not registered in csv/can2http.csv are discarded and not POSTed to HTTP.__
|
||||||
|
|
||||||
# Definition from HTTP to CANbus
|
# Definition from HTTP to CANbus
|
||||||
Not exist.
|
Not exist.
|
||||||
You can send any CAN-ID.
|
You can send any CAN-ID.
|
||||||
|
|
||||||
|
|
||||||
# Send CANBus frame using curl
|
# Send CANBus frame using curl
|
||||||
CAN-ID is specified in __decimal number__.
|
CAN-ID is specified in __decimal number__.
|
||||||
```
|
```
|
||||||
$ curl -X POST -H "Content-Type: application/json" -d '{"canid": 513, "frame": "standard", "data": [16, 17, 18]}' http://esp32-server.local:8000/api/twai/send
|
$ curl -X POST -H "Content-Type: application/json" -d '{"canid": 513, "frame": "standard", "data": [16, 17, 18]}' http://esp32-server.local:8000/api/twai/send
|
||||||
twai send successfully
|
twai send successfully
|
||||||
|
|
||||||
$ curl -X POST -H "Content-Type: application/json" -d '{"canid": 513, "frame": "extended", "data": [16, 17, 18]}' http://esp32-server.local:8000/api/twai/send
|
$ curl -X POST -H "Content-Type: application/json" -d '{"canid": 513, "frame": "extended", "data": [16, 17, 18]}' http://esp32-server.local:8000/api/twai/send
|
||||||
twai send successfully
|
twai send successfully
|
||||||
```
|
```
|
||||||
|
|
||||||
CANBus reception using UNO.
|
CANBus reception using UNO.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# HTTP Server Using Tornado
|
# HTTP Server Using Tornado
|
||||||
```
|
```
|
||||||
cd $HOME
|
cd $HOME
|
||||||
sudo apt install python3-pip python3-setuptools
|
sudo apt install python3-pip python3-setuptools
|
||||||
python3 -m pip install -U pip
|
python3 -m pip install -U pip
|
||||||
python3 -m pip install -U wheel
|
python3 -m pip install -U wheel
|
||||||
python3 -m pip install tornado
|
python3 -m pip install tornado
|
||||||
git clone https://github.com/nopnop2002/esp-idf-can2http
|
git clone https://github.com/nopnop2002/esp-idf-can2http
|
||||||
cd esp-idf-can2http
|
cd esp-idf-can2http
|
||||||
cd tornado
|
cd tornado
|
||||||
python3 can.py
|
python3 can.py
|
||||||
```
|
```
|
||||||
|
|
||||||
You can specify the number of lines to display and the port number.
|
You can specify the number of lines to display and the port number.
|
||||||
The default port number is 8000 and the default number of display lines is 20.
|
The default port number is 8000 and the default number of display lines is 20.
|
||||||
Redisplay every 5 seconds.
|
Redisplay every 5 seconds.
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
# HTTP Server Using Flask
|
# HTTP Server Using Flask
|
||||||
```
|
```
|
||||||
cd $HOME
|
cd $HOME
|
||||||
sudo apt install python3-pip python3-setuptools
|
sudo apt install python3-pip python3-setuptools
|
||||||
python3 -m pip install -U pip
|
python3 -m pip install -U pip
|
||||||
python3 -m pip install -U wheel
|
python3 -m pip install -U wheel
|
||||||
python3 -m pip install -U Werkzeug
|
python3 -m pip install -U Werkzeug
|
||||||
python3 -m pip install flask
|
python3 -m pip install flask
|
||||||
git clone https://github.com/nopnop2002/esp-idf-can2http
|
git clone https://github.com/nopnop2002/esp-idf-can2http
|
||||||
cd esp-idf-can2http
|
cd esp-idf-can2http
|
||||||
cd flask
|
cd flask
|
||||||
python3 can.py
|
python3 can.py
|
||||||
```
|
```
|
||||||
|
|
||||||
You can specify the number of lines to display and the port number.
|
You can specify the number of lines to display and the port number.
|
||||||
The default port number is 8000 and the default number of display lines is 20.
|
The default port number is 8000 and the default number of display lines is 20.
|
||||||
Redisplay every 5 seconds.
|
Redisplay every 5 seconds.
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
# Brows received data Using Tornado/Flask
|
# Brows received data Using Tornado/Flask
|
||||||
Open your browser and put the Server's IP in the address bar.
|
Open your browser and put the Server's IP in the address bar.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
# Visualize CAN-Frame
|
# Visualize CAN-Frame
|
||||||
|
|
||||||
## Using python
|
## Using python
|
||||||
There is a lot of information on the internet about the Python + visualization library.
|
There is a lot of information on the internet about the Python + visualization library.
|
||||||
- [matplotlib](https://matplotlib.org/)
|
- [matplotlib](https://matplotlib.org/)
|
||||||
- [seaborn](https://seaborn.pydata.org/index.html)
|
- [seaborn](https://seaborn.pydata.org/index.html)
|
||||||
- [bokeh](https://bokeh.org/)
|
- [bokeh](https://bokeh.org/)
|
||||||
- [plotly](https://plotly.com/python/)
|
- [plotly](https://plotly.com/python/)
|
||||||
|
|
||||||
## Using node.js
|
## Using node.js
|
||||||
There is a lot of information on the internet about the node.js + __real time__ visualization library.
|
There is a lot of information on the internet about the node.js + __real time__ visualization library.
|
||||||
- [epoch](https://epochjs.github.io/epoch/real-time/)
|
- [epoch](https://epochjs.github.io/epoch/real-time/)
|
||||||
- [plotly](https://plotly.com/javascript/streaming/)
|
- [plotly](https://plotly.com/javascript/streaming/)
|
||||||
- [chartjs-plugin-streaming](https://nagix.github.io/chartjs-plugin-streaming/1.9.0/)
|
- [chartjs-plugin-streaming](https://nagix.github.io/chartjs-plugin-streaming/1.9.0/)
|
||||||
|
|
||||||
# Troubleshooting
|
# Troubleshooting
|
||||||
There is a module of SN65HVD230 like this.
|
There is a module of SN65HVD230 like this.
|
||||||

|

|
||||||
|
|
||||||
There is a __120 ohms__ terminating resistor on the left side.
|
There is a __120 ohms__ terminating resistor on the left side.
|
||||||

|

|
||||||
|
|
||||||
I have removed the terminating resistor.
|
I have removed the terminating resistor.
|
||||||
And I used a external resistance of __150 ohms__.
|
And I used a external resistance of __150 ohms__.
|
||||||
A transmission fail is fixed.
|
A transmission fail is fixed.
|
||||||

|

|
||||||
|
|
||||||
If the transmission fails, these are the possible causes.
|
If the transmission fails, these are the possible causes.
|
||||||
- There is no receiving app on CanBus.
|
- There is no receiving app on CanBus.
|
||||||
- The speed does not match the receiver.
|
- The speed does not match the receiver.
|
||||||
- There is no terminating resistor on the CanBus.
|
- There is no terminating resistor on the CanBus.
|
||||||
- There are three terminating resistors on the CanBus.
|
- There are three terminating resistors on the CanBus.
|
||||||
- The resistance value of the terminating resistor is incorrect.
|
- The resistance value of the terminating resistor is incorrect.
|
||||||
- Stub length in CAN bus is too long. See [here](https://e2e.ti.com/support/interface-group/interface/f/interface-forum/378932/iso1050-can-bus-stub-length).
|
- Stub length in CAN bus is too long. See [here](https://e2e.ti.com/support/interface-group/interface/f/interface-forum/378932/iso1050-can-bus-stub-length).
|
||||||
|
|
||||||
# Reference
|
# Reference
|
||||||
https://github.com/nopnop2002/esp-idf-candump
|
https://github.com/nopnop2002/esp-idf-candump
|
||||||
|
|
||||||
https://github.com/nopnop2002/esp-idf-can2mqtt
|
https://github.com/nopnop2002/esp-idf-can2mqtt
|
||||||
|
|
||||||
https://github.com/nopnop2002/esp-idf-can2usb
|
https://github.com/nopnop2002/esp-idf-can2usb
|
||||||
|
|
||||||
https://github.com/nopnop2002/esp-idf-can2websocket
|
https://github.com/nopnop2002/esp-idf-can2websocket
|
||||||
|
|
||||||
https://github.com/nopnop2002/esp-idf-can2socket
|
https://github.com/nopnop2002/esp-idf-can2socket
|
||||||
|
|
||||||
https://github.com/nopnop2002/esp-idf-CANBus-Monitor
|
https://github.com/nopnop2002/esp-idf-CANBus-Monitor
|
||||||
|
|
||||||
|
|||||||
+11
-11
@@ -1,11 +1,11 @@
|
|||||||
#The file can2http.csv has three columns.
|
#The file can2http.csv has three columns.
|
||||||
#In the first column you need to specify the CAN Frame type.
|
#In the first column you need to specify the CAN Frame type.
|
||||||
#The CAN frame type is either S(Standard frame) or E(Extended frame).
|
#The CAN frame type is either S(Standard frame) or E(Extended frame).
|
||||||
#In the second column you have to specify the CAN-ID as a __hexdecimal number__.
|
#In the second column you have to specify the CAN-ID as a __hexdecimal number__.
|
||||||
#In the last column you have to specify the PATH of external web server.
|
#In the last column you have to specify the PATH of external web server.
|
||||||
#Each CAN-ID is allowed to appear only once in the whole file.
|
#Each CAN-ID is allowed to appear only once in the whole file.
|
||||||
|
|
||||||
S,101,/post
|
S,101,/post
|
||||||
E,101,/post
|
E,101,/post
|
||||||
S,103,/post
|
S,103,/post
|
||||||
E,103,/post
|
E,103,/post
|
||||||
|
|||||||
|
+78
-78
@@ -1,79 +1,79 @@
|
|||||||
<h1>Sillyfilly CAN Interface</h1>
|
<h1>Sillyfilly CAN Interface</h1>
|
||||||
<form id="txform">
|
<form id="txform">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="canidi">CAN ID (decimal)</label>
|
<label for="canidi">CAN ID (decimal)</label>
|
||||||
<input type="text" name="canidi" class="form-control" value="257" />
|
<input type="text" name="canidi" class="form-control" value="257" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Frame Type</label><br />
|
<label>Frame Type</label><br />
|
||||||
<label for="standard">Standard</label>
|
<label for="standard">Standard</label>
|
||||||
<input type="radio" id="standard" name="frame" value="standard" checked /><br />
|
<input type="radio" id="standard" name="frame" value="standard" checked /><br />
|
||||||
<label for="extended">Extended</label>
|
<label for="extended">Extended</label>
|
||||||
<input type="radio" name="frame" id="extended" value="extended" />
|
<input type="radio" name="frame" id="extended" value="extended" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="datai">Standard (decimal seperated by commas)</label>
|
<label for="datai">Standard (decimal seperated by commas)</label>
|
||||||
<input type="text" id="datai" name="datai" value="16,17,18" />
|
<input type="text" id="datai" name="datai" value="16,17,18" />
|
||||||
</div>
|
</div>
|
||||||
<input type="button" id="send" value="Send >>" onclick="send_tx()" />
|
<input type="button" id="send" value="Send >>" onclick="send_tx()" />
|
||||||
<h3>TX</h3>
|
<h3>TX</h3>
|
||||||
<div id="output">none yet</div>
|
<div id="output">none yet</div>
|
||||||
<h3>RX</h3>
|
<h3>RX</h3>
|
||||||
<div id="frames">none yet</div>
|
<div id="frames">none yet</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var clearedtx = 0;
|
var clearedtx = 0;
|
||||||
var clearedrx = 0;
|
var clearedrx = 0;
|
||||||
|
|
||||||
function mapFn(element, index) {
|
function mapFn(element, index) {
|
||||||
return parseInt(element);
|
return parseInt(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
function send_tx() {
|
function send_tx() {
|
||||||
var form = document.getElementById('txform');
|
var form = document.getElementById('txform');
|
||||||
var datai = document.getElementById('datai').value;
|
var datai = document.getElementById('datai').value;
|
||||||
var datai_arr = Array.from(datai.split(","), mapFn);
|
var datai_arr = Array.from(datai.split(","), mapFn);
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
var formData = new FormData(form);
|
var formData = new FormData(form);
|
||||||
//var txHTML = document.getElementById('output');
|
//var txHTML = document.getElementById('output');
|
||||||
//open the request
|
//open the request
|
||||||
xhr.open('POST','/api/twai/send');
|
xhr.open('POST','/api/twai/send');
|
||||||
xhr.setRequestHeader("Content-Type", "application/json");
|
xhr.setRequestHeader("Content-Type", "application/json");
|
||||||
//prepare da dataz
|
//prepare da dataz
|
||||||
var obj = Object.fromEntries(formData);
|
var obj = Object.fromEntries(formData);
|
||||||
//obj["data"] = datai.split(",");
|
//obj["data"] = datai.split(",");
|
||||||
obj["data"] = datai_arr;
|
obj["data"] = datai_arr;
|
||||||
obj["canid"] = parseInt(obj["canidi"]);
|
obj["canid"] = parseInt(obj["canidi"]);
|
||||||
delete obj.datai;
|
delete obj.datai;
|
||||||
delete obj.canidi;
|
delete obj.canidi;
|
||||||
console.log(obj);
|
console.log(obj);
|
||||||
var JSONstring = JSON.stringify(obj);
|
var JSONstring = JSON.stringify(obj);
|
||||||
|
|
||||||
xhr.send(JSONstring);
|
xhr.send(JSONstring);
|
||||||
xhr.onreadystatechange = function() {
|
xhr.onreadystatechange = function() {
|
||||||
if (xhr.readyState == XMLHttpRequest.DONE) {
|
if (xhr.readyState == XMLHttpRequest.DONE) {
|
||||||
if(clearedtx === 0) { document.getElementById('output').innerHTML=""; clearedtx = 1; }
|
if(clearedtx === 0) { document.getElementById('output').innerHTML=""; clearedtx = 1; }
|
||||||
clearedtx = 1;
|
clearedtx = 1;
|
||||||
document.getElementById('output').innerHTML += xhr.responseText+": "+JSONstring+"<br>";
|
document.getElementById('output').innerHTML += xhr.responseText+": "+JSONstring+"<br>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_rx() {
|
function update_rx() {
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
//var rxHTML = document.getElementById('frames');
|
//var rxHTML = document.getElementById('frames');
|
||||||
xhr.open('GET','/api/twai/read');
|
xhr.open('GET','/api/twai/read');
|
||||||
xhr.send();
|
xhr.send();
|
||||||
xhr.onreadystatechange = function() {
|
xhr.onreadystatechange = function() {
|
||||||
if (xhr.readyState == XMLHttpRequest.DONE) {
|
if (xhr.readyState == XMLHttpRequest.DONE) {
|
||||||
if(clearedrx === 0) { document.getElementById('frames').innerHTML=""; clearedrx = 1; }
|
if(clearedrx === 0) { document.getElementById('frames').innerHTML=""; clearedrx = 1; }
|
||||||
document.getElementById('frames').innerHTML += xhr.responseText;
|
document.getElementById('frames').innerHTML += xhr.responseText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(update_rx,1500);
|
setInterval(update_rx,1500);
|
||||||
</script>
|
</script>
|
||||||
+80
-80
@@ -1,80 +1,80 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Simple REST Server
|
# Simple REST Server
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
import argparse
|
import argparse
|
||||||
from flask import Flask, request, render_template
|
from flask import Flask, request, render_template
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
database = []
|
database = []
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def root():
|
def root():
|
||||||
global database
|
global database
|
||||||
items = []
|
items = []
|
||||||
for data in database:
|
for data in database:
|
||||||
#print("{}".format(data))
|
#print("{}".format(data))
|
||||||
datetime = data[0].split()
|
datetime = data[0].split()
|
||||||
#print("data={} datetime={}".format(data[0], datetime))
|
#print("data={} datetime={}".format(data[0], datetime))
|
||||||
|
|
||||||
items.append({
|
items.append({
|
||||||
"date": datetime[0],
|
"date": datetime[0],
|
||||||
"time": datetime[1],
|
"time": datetime[1],
|
||||||
"id": data[1],
|
"id": data[1],
|
||||||
"frame": data[2],
|
"frame": data[2],
|
||||||
"value": data[3]
|
"value": data[3]
|
||||||
})
|
})
|
||||||
#print("items={}".format(items))
|
#print("items={}".format(items))
|
||||||
return render_template("index.html", lines=app.config['lines'], items=items)
|
return render_template("index.html", lines=app.config['lines'], items=items)
|
||||||
|
|
||||||
#curl -X POST -H "Content-Type: application/json" -d '{"canid":101, "frame":"standard" , "data": [1,2,3,4,5,6,7,8]}' http://192.168.10.43:8000/post
|
#curl -X POST -H "Content-Type: application/json" -d '{"canid":101, "frame":"standard" , "data": [1,2,3,4,5,6,7,8]}' http://192.168.10.43:8000/post
|
||||||
@app.route("/post", methods=["POST"])
|
@app.route("/post", methods=["POST"])
|
||||||
def post():
|
def post():
|
||||||
function = sys._getframe().f_code.co_name
|
function = sys._getframe().f_code.co_name
|
||||||
#print("{}: request={}".format(function, request))
|
#print("{}: request={}".format(function, request))
|
||||||
#print("{}: request.data={}".format(function, request.data))
|
#print("{}: request.data={}".format(function, request.data))
|
||||||
dict = json.loads(request.data)
|
dict = json.loads(request.data)
|
||||||
print("{} dict={}".format(function, dict))
|
print("{} dict={}".format(function, dict))
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
items.append(now.strftime("%Y/%m/%d %H:%M:%S"))
|
items.append(now.strftime("%Y/%m/%d %H:%M:%S"))
|
||||||
if ("canid" in dict):
|
if ("canid" in dict):
|
||||||
print("{} canid=0x{:x}".format(function, dict['canid']))
|
print("{} canid=0x{:x}".format(function, dict['canid']))
|
||||||
items.append(dict['canid'])
|
items.append(dict['canid'])
|
||||||
|
|
||||||
if ("frame" in dict):
|
if ("frame" in dict):
|
||||||
print("{} frame={}".format(function, dict['frame']))
|
print("{} frame={}".format(function, dict['frame']))
|
||||||
items.append(dict['frame'])
|
items.append(dict['frame'])
|
||||||
|
|
||||||
if ("data" in dict):
|
if ("data" in dict):
|
||||||
print("{} data length={}".format(function, len(dict['data'])))
|
print("{} data length={}".format(function, len(dict['data'])))
|
||||||
print("{} data={}".format(function, dict['data']))
|
print("{} data={}".format(function, dict['data']))
|
||||||
items.append(dict['data'])
|
items.append(dict['data'])
|
||||||
|
|
||||||
global database
|
global database
|
||||||
#print("{} {} {}".format(type(database), len(database), database))
|
#print("{} {} {}".format(type(database), len(database), database))
|
||||||
print("lines={}".format(app.config['lines']))
|
print("lines={}".format(app.config['lines']))
|
||||||
#if(len(database) >= 20):
|
#if(len(database) >= 20):
|
||||||
if(len(database) >= app.config['lines']):
|
if(len(database) >= app.config['lines']):
|
||||||
database.pop(0)
|
database.pop(0)
|
||||||
database.append(items)
|
database.append(items)
|
||||||
|
|
||||||
data = json.dumps(['result', 'ok'])
|
data = json.dumps(['result', 'ok'])
|
||||||
return data
|
return data
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('-port', type=int, default=8000)
|
parser.add_argument('-port', type=int, default=8000)
|
||||||
parser.add_argument('-lines', type=int, default=20)
|
parser.add_argument('-lines', type=int, default=20)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
print("port={}".format(args.port))
|
print("port={}".format(args.port))
|
||||||
print("lines={}".format(args.lines))
|
print("lines={}".format(args.lines))
|
||||||
app.config['lines'] = args.lines
|
app.config['lines'] = args.lines
|
||||||
#app.run()
|
#app.run()
|
||||||
app.run(host='127.0.0.1', port=args.port, debug=True)
|
app.run(host='127.0.0.1', port=args.port, debug=True)
|
||||||
|
|
||||||
|
|||||||
+35
-35
@@ -1,35 +1,35 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
<meta http-equiv="refresh" content="5;url="/">
|
<meta http-equiv="refresh" content="5;url="/">
|
||||||
<title>CAN DATA</title>
|
<title>CAN DATA</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
Display the latest {{ lines }} records.<br>
|
Display the latest {{ lines }} records.<br>
|
||||||
If you want to see more, specify the number of lines at startup.<br>
|
If you want to see more, specify the number of lines at startup.<br>
|
||||||
|
|
||||||
<table border="1" cellpadding="2" cellspacing="2">
|
<table border="1" cellpadding="2" cellspacing="2">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr style="color:#ffffff;" bgcolor="#800000">
|
<tr style="color:#ffffff;" bgcolor="#800000">
|
||||||
<th valign="top">Date</th>
|
<th valign="top">Date</th>
|
||||||
<th valign="top">Time</th>
|
<th valign="top">Time</th>
|
||||||
<th valign="top">ID</th>
|
<th valign="top">ID</th>
|
||||||
<th valign="top">Frame</th>
|
<th valign="top">Frame</th>
|
||||||
<th valign="top">Value</th>
|
<th valign="top">Value</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% for i in items %}
|
{% for i in items %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ i.date }}</td>
|
<td>{{ i.date }}</td>
|
||||||
<td>{{ i.time }}</td>
|
<td>{{ i.time }}</td>
|
||||||
<td>{{ i.id }}</td>
|
<td>{{ i.id }}</td>
|
||||||
<td>{{ i.frame }}</td>
|
<td>{{ i.frame }}</td>
|
||||||
<td>{{ i.value }}</td>
|
<td>{{ i.value }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+4
-4
@@ -1,4 +1,4 @@
|
|||||||
set(COMPONENT_SRCS "main.c" "http_post.c" "http_server.c" "twai.c")
|
set(COMPONENT_SRCS "main.c" "http_post.c" "http_server.c" "twai.c")
|
||||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||||
|
|
||||||
register_component()
|
register_component()
|
||||||
|
|||||||
+152
-152
@@ -1,152 +1,152 @@
|
|||||||
menu "Sillyfilly-CAN Configuration"
|
menu "Sillyfilly-CAN Configuration"
|
||||||
|
|
||||||
config GPIO_RANGE_MAX
|
config GPIO_RANGE_MAX
|
||||||
int
|
int
|
||||||
default 33 if IDF_TARGET_ESP32
|
default 33 if IDF_TARGET_ESP32
|
||||||
default 46 if IDF_TARGET_ESP32S2
|
default 46 if IDF_TARGET_ESP32S2
|
||||||
default 48 if IDF_TARGET_ESP32S3
|
default 48 if IDF_TARGET_ESP32S3
|
||||||
default 19 if IDF_TARGET_ESP32C3
|
default 19 if IDF_TARGET_ESP32C3
|
||||||
default 30 if IDF_TARGET_ESP32C6
|
default 30 if IDF_TARGET_ESP32C6
|
||||||
|
|
||||||
menu "CAN Setting"
|
menu "CAN Setting"
|
||||||
|
|
||||||
choice CAN_BITRATE
|
choice CAN_BITRATE
|
||||||
prompt "CAN Bitrate"
|
prompt "CAN Bitrate"
|
||||||
default CAN_BITRATE_500
|
default CAN_BITRATE_500
|
||||||
help
|
help
|
||||||
Select the CAN bitrate for the example.
|
Select the CAN bitrate for the example.
|
||||||
config CAN_BITRATE_25
|
config CAN_BITRATE_25
|
||||||
bool "BITRATE_25"
|
bool "BITRATE_25"
|
||||||
help
|
help
|
||||||
CAN bitrate is 25 Kbit/s.
|
CAN bitrate is 25 Kbit/s.
|
||||||
config CAN_BITRATE_50
|
config CAN_BITRATE_50
|
||||||
bool "BITRATE_50"
|
bool "BITRATE_50"
|
||||||
help
|
help
|
||||||
CAN bitrate is 50 Kbit/s.
|
CAN bitrate is 50 Kbit/s.
|
||||||
config CAN_BITRATE_100
|
config CAN_BITRATE_100
|
||||||
bool "BITRATE_100"
|
bool "BITRATE_100"
|
||||||
help
|
help
|
||||||
CAN bitrate is 100 Kbit/s.
|
CAN bitrate is 100 Kbit/s.
|
||||||
config CAN_BITRATE_125
|
config CAN_BITRATE_125
|
||||||
bool "BITRATE_125"
|
bool "BITRATE_125"
|
||||||
help
|
help
|
||||||
CAN bitrate is 125 Kbit/s.
|
CAN bitrate is 125 Kbit/s.
|
||||||
config CAN_BITRATE_250
|
config CAN_BITRATE_250
|
||||||
bool "BITRATE_250"
|
bool "BITRATE_250"
|
||||||
help
|
help
|
||||||
CAN bitrate is 250 Kbit/s.
|
CAN bitrate is 250 Kbit/s.
|
||||||
config CAN_BITRATE_500
|
config CAN_BITRATE_500
|
||||||
bool "BITRATE_500"
|
bool "BITRATE_500"
|
||||||
help
|
help
|
||||||
CAN bitrate is 500 Kbit/s.
|
CAN bitrate is 500 Kbit/s.
|
||||||
config CAN_BITRATE_800
|
config CAN_BITRATE_800
|
||||||
bool "BITRATE_800"
|
bool "BITRATE_800"
|
||||||
help
|
help
|
||||||
CAN bitrate is 800 Kbit/s.
|
CAN bitrate is 800 Kbit/s.
|
||||||
config CAN_BITRATE_1000
|
config CAN_BITRATE_1000
|
||||||
bool "BITRATE_1000"
|
bool "BITRATE_1000"
|
||||||
help
|
help
|
||||||
CAN bitrate is 1 Mbit/s.
|
CAN bitrate is 1 Mbit/s.
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config CTX_GPIO
|
config CTX_GPIO
|
||||||
int "CTX GPIO number"
|
int "CTX GPIO number"
|
||||||
range 0 GPIO_RANGE_MAX
|
range 0 GPIO_RANGE_MAX
|
||||||
default 21 if IDF_TARGET_ESP32
|
default 21 if IDF_TARGET_ESP32
|
||||||
default 17 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
default 17 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||||
default 0 # C3 and others
|
default 0 # C3 and others
|
||||||
help
|
help
|
||||||
GPIO number (IOxx) to CTX.
|
GPIO number (IOxx) to CTX.
|
||||||
Some GPIOs are used for other purposes (flash connections, etc.).
|
Some GPIOs are used for other purposes (flash connections, etc.).
|
||||||
GPIOs 35-39 are input-only so cannot be used as outputs.
|
GPIOs 35-39 are input-only so cannot be used as outputs.
|
||||||
|
|
||||||
config CRX_GPIO
|
config CRX_GPIO
|
||||||
int "CRX GPIO number"
|
int "CRX GPIO number"
|
||||||
range 0 GPIO_RANGE_MAX
|
range 0 GPIO_RANGE_MAX
|
||||||
default 22 if IDF_TARGET_ESP32
|
default 22 if IDF_TARGET_ESP32
|
||||||
default 18 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
default 18 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||||
default 1 # C3 and others
|
default 1 # C3 and others
|
||||||
help
|
help
|
||||||
GPIO number (IOxx) to CRX.
|
GPIO number (IOxx) to CRX.
|
||||||
Some GPIOs are used for other purposes (flash connections, etc.).
|
Some GPIOs are used for other purposes (flash connections, etc.).
|
||||||
GPIOs 35-39 are input-only so cannot be used as outputs.
|
GPIOs 35-39 are input-only so cannot be used as outputs.
|
||||||
|
|
||||||
config ENABLE_PRINT
|
config ENABLE_PRINT
|
||||||
bool "Output the received CAN FRAME to STDOUT"
|
bool "Output the received CAN FRAME to STDOUT"
|
||||||
default true
|
default true
|
||||||
help
|
help
|
||||||
Output the received CAN FRAME to STDOUT.
|
Output the received CAN FRAME to STDOUT.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
menu "WiFi Setting"
|
menu "WiFi Setting"
|
||||||
|
|
||||||
config ESP_WIFI_SSID
|
config ESP_WIFI_SSID
|
||||||
string "WiFi SSID"
|
string "WiFi SSID"
|
||||||
default "wifi-name"
|
default "wifi-name"
|
||||||
help
|
help
|
||||||
SSID (network name) to connect to.
|
SSID (network name) to connect to.
|
||||||
|
|
||||||
config ESP_WIFI_PASSWORD
|
config ESP_WIFI_PASSWORD
|
||||||
string "WiFi Password"
|
string "WiFi Password"
|
||||||
default "wifi-password"
|
default "wifi-password"
|
||||||
help
|
help
|
||||||
WiFi password (WPA or WPA2) to connect to.
|
WiFi password (WPA or WPA2) to connect to.
|
||||||
|
|
||||||
config ESP_MAXIMUM_RETRY
|
config ESP_MAXIMUM_RETRY
|
||||||
int "Maximum retry"
|
int "Maximum retry"
|
||||||
default 5
|
default 5
|
||||||
help
|
help
|
||||||
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
|
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
|
||||||
|
|
||||||
config MDNS_HOSTNAME
|
config MDNS_HOSTNAME
|
||||||
string "mDNS Hostname"
|
string "mDNS Hostname"
|
||||||
default "esp32-can-server"
|
default "esp32-can-server"
|
||||||
help
|
help
|
||||||
The mDNS host name used by the ESP32.
|
The mDNS host name used by the ESP32.
|
||||||
|
|
||||||
config STATIC_IP
|
config STATIC_IP
|
||||||
bool "Enable Static IP Address"
|
bool "Enable Static IP Address"
|
||||||
default false
|
default false
|
||||||
help
|
help
|
||||||
Enable Static IP Address.
|
Enable Static IP Address.
|
||||||
|
|
||||||
config STATIC_IP_ADDRESS
|
config STATIC_IP_ADDRESS
|
||||||
depends on STATIC_IP
|
depends on STATIC_IP
|
||||||
string "Static IP Address"
|
string "Static IP Address"
|
||||||
default "192.168.10.100"
|
default "192.168.10.100"
|
||||||
help
|
help
|
||||||
Static IP Address for Station.
|
Static IP Address for Station.
|
||||||
|
|
||||||
config STATIC_GW_ADDRESS
|
config STATIC_GW_ADDRESS
|
||||||
depends on STATIC_IP
|
depends on STATIC_IP
|
||||||
string "Static GW Address"
|
string "Static GW Address"
|
||||||
default "192.168.10.1"
|
default "192.168.10.1"
|
||||||
help
|
help
|
||||||
Static GW Address for Station.
|
Static GW Address for Station.
|
||||||
|
|
||||||
config STATIC_NM_ADDRESS
|
config STATIC_NM_ADDRESS
|
||||||
depends on STATIC_IP
|
depends on STATIC_IP
|
||||||
string "Static Netmask"
|
string "Static Netmask"
|
||||||
default "255.255.255.0"
|
default "255.255.255.0"
|
||||||
help
|
help
|
||||||
Static Netmask for Station.
|
Static Netmask for Station.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
menu "HTTP Server Setting"
|
menu "HTTP Server Setting"
|
||||||
|
|
||||||
config WEB_SERVER
|
config WEB_SERVER
|
||||||
string "HTTP Server IP or mDNS"
|
string "HTTP Server IP or mDNS"
|
||||||
default "esp32-can-server"
|
default "esp32-can-server"
|
||||||
help
|
help
|
||||||
The host name or IP address of the HTTP server to use.
|
The host name or IP address of the HTTP server to use.
|
||||||
|
|
||||||
config WEB_PORT
|
config WEB_PORT
|
||||||
int "HTTP Server Port"
|
int "HTTP Server Port"
|
||||||
default 8000
|
default 8000
|
||||||
help
|
help
|
||||||
HTTP server port to use.
|
HTTP server port to use.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
endmenu
|
endmenu
|
||||||
|
|||||||
+4
-4
@@ -1,4 +1,4 @@
|
|||||||
#
|
#
|
||||||
# Main Makefile. This is basically the same as a component makefile.
|
# Main Makefile. This is basically the same as a component makefile.
|
||||||
#
|
#
|
||||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||||
|
|||||||
+199
-199
@@ -1,199 +1,199 @@
|
|||||||
/* ESP HTTP Client Example
|
/* ESP HTTP Client Example
|
||||||
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
Unless required by applicable law or agreed to in writing, this
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "esp_tls.h"
|
#include "esp_tls.h"
|
||||||
#include "esp_http_client.h"
|
#include "esp_http_client.h"
|
||||||
|
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
|
|
||||||
#include "twai.h"
|
#include "twai.h"
|
||||||
|
|
||||||
static const char *TAG = "HTTP";
|
static const char *TAG = "HTTP";
|
||||||
|
|
||||||
extern QueueHandle_t xQueue_http_client;
|
extern QueueHandle_t xQueue_http_client;
|
||||||
|
|
||||||
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
||||||
{
|
{
|
||||||
static char *output_buffer; // Buffer to store response of http request from event handler
|
static char *output_buffer; // Buffer to store response of http request from event handler
|
||||||
static int output_len; // Stores number of bytes read
|
static int output_len; // Stores number of bytes read
|
||||||
switch(evt->event_id) {
|
switch(evt->event_id) {
|
||||||
case HTTP_EVENT_ERROR:
|
case HTTP_EVENT_ERROR:
|
||||||
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
|
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
|
||||||
break;
|
break;
|
||||||
case HTTP_EVENT_ON_CONNECTED:
|
case HTTP_EVENT_ON_CONNECTED:
|
||||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
|
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
|
||||||
break;
|
break;
|
||||||
case HTTP_EVENT_HEADER_SENT:
|
case HTTP_EVENT_HEADER_SENT:
|
||||||
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
|
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
|
||||||
break;
|
break;
|
||||||
case HTTP_EVENT_ON_HEADER:
|
case HTTP_EVENT_ON_HEADER:
|
||||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
|
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
|
||||||
break;
|
break;
|
||||||
case HTTP_EVENT_ON_DATA:
|
case HTTP_EVENT_ON_DATA:
|
||||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
|
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
|
||||||
/*
|
/*
|
||||||
* Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data.
|
* Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data.
|
||||||
* However, event handler can also be used in case chunked encoding is used.
|
* However, event handler can also be used in case chunked encoding is used.
|
||||||
*/
|
*/
|
||||||
if (!esp_http_client_is_chunked_response(evt->client)) {
|
if (!esp_http_client_is_chunked_response(evt->client)) {
|
||||||
// If user_data buffer is configured, copy the response into the buffer
|
// If user_data buffer is configured, copy the response into the buffer
|
||||||
if (evt->user_data) {
|
if (evt->user_data) {
|
||||||
memcpy(evt->user_data + output_len, evt->data, evt->data_len);
|
memcpy(evt->user_data + output_len, evt->data, evt->data_len);
|
||||||
} else {
|
} else {
|
||||||
if (output_buffer == NULL) {
|
if (output_buffer == NULL) {
|
||||||
output_buffer = (char *) malloc(esp_http_client_get_content_length(evt->client));
|
output_buffer = (char *) malloc(esp_http_client_get_content_length(evt->client));
|
||||||
output_len = 0;
|
output_len = 0;
|
||||||
if (output_buffer == NULL) {
|
if (output_buffer == NULL) {
|
||||||
ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
|
ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy(output_buffer + output_len, evt->data, evt->data_len);
|
memcpy(output_buffer + output_len, evt->data, evt->data_len);
|
||||||
}
|
}
|
||||||
output_len += evt->data_len;
|
output_len += evt->data_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case HTTP_EVENT_ON_FINISH:
|
case HTTP_EVENT_ON_FINISH:
|
||||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
|
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
|
||||||
if (output_buffer != NULL) {
|
if (output_buffer != NULL) {
|
||||||
// Response is accumulated in output_buffer. Uncomment the below line to print the accumulated response
|
// Response is accumulated in output_buffer. Uncomment the below line to print the accumulated response
|
||||||
// ESP_LOG_BUFFER_HEX(TAG, output_buffer, output_len);
|
// ESP_LOG_BUFFER_HEX(TAG, output_buffer, output_len);
|
||||||
free(output_buffer);
|
free(output_buffer);
|
||||||
output_buffer = NULL;
|
output_buffer = NULL;
|
||||||
}
|
}
|
||||||
output_len = 0;
|
output_len = 0;
|
||||||
break;
|
break;
|
||||||
case HTTP_EVENT_DISCONNECTED:
|
case HTTP_EVENT_DISCONNECTED:
|
||||||
ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED");
|
ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED");
|
||||||
int mbedtls_err = 0;
|
int mbedtls_err = 0;
|
||||||
esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL);
|
esp_err_t err = esp_tls_get_and_clear_last_error(evt->data, &mbedtls_err, NULL);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
if (output_buffer != NULL) {
|
if (output_buffer != NULL) {
|
||||||
free(output_buffer);
|
free(output_buffer);
|
||||||
output_buffer = NULL;
|
output_buffer = NULL;
|
||||||
}
|
}
|
||||||
output_len = 0;
|
output_len = 0;
|
||||||
ESP_LOGI(TAG, "Last esp error code: 0x%x", err);
|
ESP_LOGI(TAG, "Last esp error code: 0x%x", err);
|
||||||
ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err);
|
ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
case HTTP_EVENT_REDIRECT:
|
case HTTP_EVENT_REDIRECT:
|
||||||
ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");
|
ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");
|
||||||
esp_http_client_set_header(evt->client, "From", "user@example.com");
|
esp_http_client_set_header(evt->client, "From", "user@example.com");
|
||||||
esp_http_client_set_header(evt->client, "Accept", "text/html");
|
esp_http_client_set_header(evt->client, "Accept", "text/html");
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_HTTP_OUTPUT_BUFFER 2048
|
#define MAX_HTTP_OUTPUT_BUFFER 2048
|
||||||
|
|
||||||
static void http_rest_with_url(char * path, char * post_data)
|
static void http_rest_with_url(char * path, char * post_data)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "path=[%s]", path);
|
ESP_LOGI(TAG, "path=[%s]", path);
|
||||||
char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
|
char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
|
||||||
/**
|
/**
|
||||||
* NOTE: All the configuration parameters for http_client must be spefied either in URL or as host and path parameters.
|
* NOTE: All the configuration parameters for http_client must be spefied either in URL or as host and path parameters.
|
||||||
* If host and path parameters are not set, query parameter will be ignored. In such cases,
|
* If host and path parameters are not set, query parameter will be ignored. In such cases,
|
||||||
* query parameter should be specified in URL.
|
* query parameter should be specified in URL.
|
||||||
*
|
*
|
||||||
* If URL as well as host and path parameters are specified, values of host and path will be considered.
|
* If URL as well as host and path parameters are specified, values of host and path will be considered.
|
||||||
*/
|
*/
|
||||||
#if 1
|
#if 1
|
||||||
esp_http_client_config_t config = {
|
esp_http_client_config_t config = {
|
||||||
.host = CONFIG_WEB_SERVER,
|
.host = CONFIG_WEB_SERVER,
|
||||||
.port = CONFIG_WEB_PORT,
|
.port = CONFIG_WEB_PORT,
|
||||||
.path = path,
|
.path = path,
|
||||||
.event_handler = _http_event_handler,
|
.event_handler = _http_event_handler,
|
||||||
.user_data = local_response_buffer, // Pass address of local buffer to get response
|
.user_data = local_response_buffer, // Pass address of local buffer to get response
|
||||||
.disable_auto_redirect = true,
|
.disable_auto_redirect = true,
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
// Same as above
|
// Same as above
|
||||||
esp_http_client_config_t config = {
|
esp_http_client_config_t config = {
|
||||||
.url = "http://http-server.local:8000/post",
|
.url = "http://http-server.local:8000/post",
|
||||||
.event_handler = _http_event_handler,
|
.event_handler = _http_event_handler,
|
||||||
.user_data = local_response_buffer, // Pass address of local buffer to get response
|
.user_data = local_response_buffer, // Pass address of local buffer to get response
|
||||||
.disable_auto_redirect = true,
|
.disable_auto_redirect = true,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||||
|
|
||||||
// POST
|
// POST
|
||||||
// no need to change url
|
// no need to change url
|
||||||
//esp_http_client_set_url(client, "http://192.168.10.43:8000/post");
|
//esp_http_client_set_url(client, "http://192.168.10.43:8000/post");
|
||||||
esp_http_client_set_method(client, HTTP_METHOD_POST);
|
esp_http_client_set_method(client, HTTP_METHOD_POST);
|
||||||
esp_http_client_set_header(client, "Content-Type", "application/json");
|
esp_http_client_set_header(client, "Content-Type", "application/json");
|
||||||
esp_http_client_set_post_field(client, post_data, strlen(post_data));
|
esp_http_client_set_post_field(client, post_data, strlen(post_data));
|
||||||
esp_err_t err = esp_http_client_perform(client);
|
esp_err_t err = esp_http_client_perform(client);
|
||||||
if (err == ESP_OK) {
|
if (err == ESP_OK) {
|
||||||
ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %lld",
|
ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %lld",
|
||||||
esp_http_client_get_status_code(client),
|
esp_http_client_get_status_code(client),
|
||||||
(int64_t)esp_http_client_get_content_length(client));
|
(int64_t)esp_http_client_get_content_length(client));
|
||||||
ESP_LOGI(TAG, "local_response_buffer=[%s]", local_response_buffer);
|
ESP_LOGI(TAG, "local_response_buffer=[%s]", local_response_buffer);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
|
ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_http_client_cleanup(client);
|
esp_http_client_cleanup(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void http_client_task(void *pvParameters)
|
void http_client_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Start HTTP Client: connect to http://%s:%d", CONFIG_WEB_SERVER, CONFIG_WEB_PORT);
|
ESP_LOGI(TAG, "Start HTTP Client: connect to http://%s:%d", CONFIG_WEB_SERVER, CONFIG_WEB_PORT);
|
||||||
FRAME_t frameBuf;
|
FRAME_t frameBuf;
|
||||||
while (1) {
|
while (1) {
|
||||||
xQueueReceive(xQueue_http_client, &frameBuf, portMAX_DELAY);
|
xQueueReceive(xQueue_http_client, &frameBuf, portMAX_DELAY);
|
||||||
ESP_LOGI(TAG, "canid=%"PRIx32" ext=%d topic=[%s]", frameBuf.canid, frameBuf.ext, frameBuf.topic);
|
ESP_LOGI(TAG, "canid=%"PRIx32" ext=%d topic=[%s]", frameBuf.canid, frameBuf.ext, frameBuf.topic);
|
||||||
for(int i=0;i<frameBuf.data_len;i++) {
|
for(int i=0;i<frameBuf.data_len;i++) {
|
||||||
ESP_LOGI(TAG, "DATA=%x", frameBuf.data[i]);
|
ESP_LOGI(TAG, "DATA=%x", frameBuf.data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build JSON string
|
// build JSON string
|
||||||
cJSON *root;
|
cJSON *root;
|
||||||
root = cJSON_CreateObject();
|
root = cJSON_CreateObject();
|
||||||
cJSON_AddNumberToObject(root, "canid", frameBuf.canid);
|
cJSON_AddNumberToObject(root, "canid", frameBuf.canid);
|
||||||
if (frameBuf.ext == 0) {
|
if (frameBuf.ext == 0) {
|
||||||
cJSON_AddStringToObject(root, "frame", "standard");
|
cJSON_AddStringToObject(root, "frame", "standard");
|
||||||
} else {
|
} else {
|
||||||
cJSON_AddStringToObject(root, "frame", "extended");
|
cJSON_AddStringToObject(root, "frame", "extended");
|
||||||
}
|
}
|
||||||
cJSON *dataArray;
|
cJSON *dataArray;
|
||||||
dataArray = cJSON_CreateArray();
|
dataArray = cJSON_CreateArray();
|
||||||
cJSON_AddItemToObject(root, "data", dataArray);
|
cJSON_AddItemToObject(root, "data", dataArray);
|
||||||
for(int i=0;i<frameBuf.data_len;i++) {
|
for(int i=0;i<frameBuf.data_len;i++) {
|
||||||
cJSON *dataItem = NULL;
|
cJSON *dataItem = NULL;
|
||||||
dataItem = cJSON_CreateNumber(frameBuf.data[i]);
|
dataItem = cJSON_CreateNumber(frameBuf.data[i]);
|
||||||
cJSON_AddItemToArray(dataArray, dataItem);
|
cJSON_AddItemToArray(dataArray, dataItem);
|
||||||
}
|
}
|
||||||
char *json_string = cJSON_Print(root);
|
char *json_string = cJSON_Print(root);
|
||||||
ESP_LOGI(TAG, "json_string\n%s",json_string);
|
ESP_LOGI(TAG, "json_string\n%s",json_string);
|
||||||
cJSON_Delete(root);
|
cJSON_Delete(root);
|
||||||
|
|
||||||
//char *post_data = "{\"canid\":257}";
|
//char *post_data = "{\"canid\":257}";
|
||||||
//http_rest_with_url(frameBuf.topic, post_data);
|
//http_rest_with_url(frameBuf.topic, post_data);
|
||||||
http_rest_with_url(frameBuf.topic, json_string);
|
http_rest_with_url(frameBuf.topic, json_string);
|
||||||
cJSON_free(json_string);
|
cJSON_free(json_string);
|
||||||
} // end while
|
} // end while
|
||||||
|
|
||||||
// Never reach here
|
// Never reach here
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
+369
-369
@@ -1,369 +1,369 @@
|
|||||||
/* HTTP Server Example
|
/* HTTP Server Example
|
||||||
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
Unless required by applicable law or agreed to in writing, this
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/queue.h"
|
#include "freertos/queue.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_vfs.h"
|
#include "esp_vfs.h"
|
||||||
#include "esp_spiffs.h"
|
#include "esp_spiffs.h"
|
||||||
#include "esp_http_server.h"
|
#include "esp_http_server.h"
|
||||||
#include "esp_chip_info.h"
|
#include "esp_chip_info.h"
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
#include "driver/twai.h"
|
#include "driver/twai.h"
|
||||||
#include "twai.h"
|
#include "twai.h"
|
||||||
|
|
||||||
#define SCRATCH_BUFSIZE (1024)
|
#define SCRATCH_BUFSIZE (1024)
|
||||||
|
|
||||||
#define TAG "HTTP_SERVER"
|
#define TAG "HTTP_SERVER"
|
||||||
|
|
||||||
int pointer = 0;
|
int pointer = 0;
|
||||||
static char *base_path = "/spiffs";
|
static char *base_path = "/spiffs";
|
||||||
|
|
||||||
extern QueueHandle_t xQueue_twai_tx;
|
extern QueueHandle_t xQueue_twai_tx;
|
||||||
extern char* twai_string_buf;
|
extern char* twai_string_buf;
|
||||||
extern int twai_allocation_size;
|
extern int twai_allocation_size;
|
||||||
extern char* file_read_buf;
|
extern char* file_read_buf;
|
||||||
extern int allocation_size;
|
extern int allocation_size;
|
||||||
|
|
||||||
typedef struct rest_server_context {
|
typedef struct rest_server_context {
|
||||||
char base_path[ESP_VFS_PATH_MAX + 1]; // Not used in this project
|
char base_path[ESP_VFS_PATH_MAX + 1]; // Not used in this project
|
||||||
char scratch[SCRATCH_BUFSIZE];
|
char scratch[SCRATCH_BUFSIZE];
|
||||||
} rest_server_context_t;
|
} rest_server_context_t;
|
||||||
|
|
||||||
esp_err_t readFile(char *ifile) {
|
esp_err_t readFile(char *ifile) {
|
||||||
int c;
|
int c;
|
||||||
ESP_LOGI(TAG, "File read llocated memory confirmed!: %d bytes", allocation_size);
|
ESP_LOGI(TAG, "File read llocated memory confirmed!: %d bytes", allocation_size);
|
||||||
char *spiffspath = "/spiffs";
|
char *spiffspath = "/spiffs";
|
||||||
int buflen = strlen(spiffspath)+strlen(ifile)+1;
|
int buflen = strlen(spiffspath)+strlen(ifile)+1;
|
||||||
char buf[buflen];
|
char buf[buflen];
|
||||||
snprintf(buf, sizeof(buf), "%s%s", spiffspath, ifile);
|
snprintf(buf, sizeof(buf), "%s%s", spiffspath, ifile);
|
||||||
ESP_LOGI(TAG, "buflen: %d, spiffspath: %s, ifile: %s, buf: %s, base_path: %s",buflen,spiffspath,ifile,buf,base_path);
|
ESP_LOGI(TAG, "buflen: %d, spiffspath: %s, ifile: %s, buf: %s, base_path: %s",buflen,spiffspath,ifile,buf,base_path);
|
||||||
FILE* f = fopen(buf, "r");
|
FILE* f = fopen(buf, "r");
|
||||||
ESP_LOGI(TAG, "Begin reading file");
|
ESP_LOGI(TAG, "Begin reading file");
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while ((c = fgetc(f)) != EOF) {
|
while ((c = fgetc(f)) != EOF) {
|
||||||
file_read_buf[i] = c;
|
file_read_buf[i] = c;
|
||||||
i++;
|
i++;
|
||||||
};
|
};
|
||||||
file_read_buf[i] = '\0';
|
file_read_buf[i] = '\0';
|
||||||
fclose(f);
|
fclose(f);
|
||||||
ESP_LOGI(TAG, "Read File - Iterations: %d", i);
|
ESP_LOGI(TAG, "Read File - Iterations: %d", i);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handler for roor get handler */
|
/* Handler for roor get handler */
|
||||||
esp_err_t root_get_handler(httpd_req_t *req)
|
esp_err_t root_get_handler(httpd_req_t *req)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "root_get_handler req->uri=[%s]", req->uri);
|
ESP_LOGI(TAG, "root_get_handler req->uri=[%s]", req->uri);
|
||||||
readFile("/index.html");
|
readFile("/index.html");
|
||||||
esp_err_t sendcheck = httpd_resp_send(req, file_read_buf, HTTPD_RESP_USE_STRLEN);
|
esp_err_t sendcheck = httpd_resp_send(req, file_read_buf, HTTPD_RESP_USE_STRLEN);
|
||||||
//httpd_resp_sendstr_chunk(req, NULL);
|
//httpd_resp_sendstr_chunk(req, NULL);
|
||||||
|
|
||||||
if(sendcheck == ESP_OK) {
|
if(sendcheck == ESP_OK) {
|
||||||
//free(file_read_buf);
|
//free(file_read_buf);
|
||||||
memset(twai_string_buf, '\0', allocation_size);
|
memset(twai_string_buf, '\0', allocation_size);
|
||||||
ESP_LOGI(TAG, "malloc freed");
|
ESP_LOGI(TAG, "malloc freed");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
} else {
|
} else {
|
||||||
return ESP_ERR_HTTPD_RESP_SEND;
|
return ESP_ERR_HTTPD_RESP_SEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t twai_read_handler(httpd_req_t *req)
|
static esp_err_t twai_read_handler(httpd_req_t *req)
|
||||||
{
|
{
|
||||||
httpd_resp_sendstr(req, twai_string_buf);
|
httpd_resp_sendstr(req, twai_string_buf);
|
||||||
// Buffers returned by cJSON_Print must be freed by the caller.
|
// Buffers returned by cJSON_Print must be freed by the caller.
|
||||||
// Please use the proper API (cJSON_free) rather than directly
|
// Please use the proper API (cJSON_free) rather than directly
|
||||||
//twai_string_buf = {0};
|
//twai_string_buf = {0};
|
||||||
memset(twai_string_buf, '\0', twai_allocation_size);
|
memset(twai_string_buf, '\0', twai_allocation_size);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handler for getting system information handler */
|
/* Handler for getting system information handler */
|
||||||
// curl 'http://esp32-can-server:8000/api/system/info' | python -m json.tool
|
// curl 'http://esp32-can-server:8000/api/system/info' | python -m json.tool
|
||||||
static esp_err_t system_info_get_handler(httpd_req_t *req)
|
static esp_err_t system_info_get_handler(httpd_req_t *req)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "system_info_get_handler req->uri=[%s]", req->uri);
|
ESP_LOGI(TAG, "system_info_get_handler req->uri=[%s]", req->uri);
|
||||||
httpd_resp_set_type(req, "application/json");
|
httpd_resp_set_type(req, "application/json");
|
||||||
cJSON *root = cJSON_CreateObject();
|
cJSON *root = cJSON_CreateObject();
|
||||||
esp_chip_info_t chip_info;
|
esp_chip_info_t chip_info;
|
||||||
esp_chip_info(&chip_info);
|
esp_chip_info(&chip_info);
|
||||||
cJSON_AddStringToObject(root, "version", IDF_VER);
|
cJSON_AddStringToObject(root, "version", IDF_VER);
|
||||||
cJSON_AddNumberToObject(root, "cores", chip_info.cores);
|
cJSON_AddNumberToObject(root, "cores", chip_info.cores);
|
||||||
//const char *sys_info = cJSON_Print(root);
|
//const char *sys_info = cJSON_Print(root);
|
||||||
char *sys_info = cJSON_Print(root);
|
char *sys_info = cJSON_Print(root);
|
||||||
httpd_resp_sendstr(req, sys_info);
|
httpd_resp_sendstr(req, sys_info);
|
||||||
// Buffers returned by cJSON_Print must be freed by the caller.
|
// Buffers returned by cJSON_Print must be freed by the caller.
|
||||||
// Please use the proper API (cJSON_free) rather than directly calling stdlib free.
|
// Please use the proper API (cJSON_free) rather than directly calling stdlib free.
|
||||||
cJSON_free(sys_info);
|
cJSON_free(sys_info);
|
||||||
cJSON_Delete(root);
|
cJSON_Delete(root);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create array
|
// Create array
|
||||||
cJSON *Create_array_of_anything(cJSON **objects,int array_num)
|
cJSON *Create_array_of_anything(cJSON **objects,int array_num)
|
||||||
{
|
{
|
||||||
cJSON *prev = 0;
|
cJSON *prev = 0;
|
||||||
cJSON *root;
|
cJSON *root;
|
||||||
root = cJSON_CreateArray();
|
root = cJSON_CreateArray();
|
||||||
for (int i=0;i<array_num;i++) {
|
for (int i=0;i<array_num;i++) {
|
||||||
if (!i) {
|
if (!i) {
|
||||||
root->child=objects[i];
|
root->child=objects[i];
|
||||||
} else {
|
} else {
|
||||||
prev->next=objects[i];
|
prev->next=objects[i];
|
||||||
objects[i]->prev=prev;
|
objects[i]->prev=prev;
|
||||||
}
|
}
|
||||||
prev=objects[i];
|
prev=objects[i];
|
||||||
}
|
}
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *JSON_Types(int type) {
|
char *JSON_Types(int type) {
|
||||||
if (type == cJSON_Invalid) return ("cJSON_Invalid");
|
if (type == cJSON_Invalid) return ("cJSON_Invalid");
|
||||||
if (type == cJSON_False) return ("cJSON_False");
|
if (type == cJSON_False) return ("cJSON_False");
|
||||||
if (type == cJSON_True) return ("cJSON_True");
|
if (type == cJSON_True) return ("cJSON_True");
|
||||||
if (type == cJSON_NULL) return ("cJSON_NULL");
|
if (type == cJSON_NULL) return ("cJSON_NULL");
|
||||||
if (type == cJSON_Number) return ("cJSON_Number");
|
if (type == cJSON_Number) return ("cJSON_Number");
|
||||||
if (type == cJSON_String) return ("cJSON_String");
|
if (type == cJSON_String) return ("cJSON_String");
|
||||||
if (type == cJSON_Array) return ("cJSON_Array");
|
if (type == cJSON_Array) return ("cJSON_Array");
|
||||||
if (type == cJSON_Object) return ("cJSON_Object");
|
if (type == cJSON_Object) return ("cJSON_Object");
|
||||||
if (type == cJSON_Raw) return ("cJSON_Raw");
|
if (type == cJSON_Raw) return ("cJSON_Raw");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handler for twai send handler */
|
/* Handler for twai send handler */
|
||||||
// curl -X POST -H "Content-Type: application/json" -d '{"canid": 513, "frame": "standard", "data": [11, 12, 13, 14]}' http://esp32-server.local:8000/api/twai/send
|
// curl -X POST -H "Content-Type: application/json" -d '{"canid": 513, "frame": "standard", "data": [11, 12, 13, 14]}' http://esp32-server.local:8000/api/twai/send
|
||||||
static esp_err_t twai_send_handler(httpd_req_t *req)
|
static esp_err_t twai_send_handler(httpd_req_t *req)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "twai_send_handler req->uri=[%s]", req->uri);
|
ESP_LOGI(TAG, "twai_send_handler req->uri=[%s]", req->uri);
|
||||||
int total_len = req->content_len;
|
int total_len = req->content_len;
|
||||||
int cur_len = 0;
|
int cur_len = 0;
|
||||||
char *buf = ((rest_server_context_t *)(req->user_ctx))->scratch;
|
char *buf = ((rest_server_context_t *)(req->user_ctx))->scratch;
|
||||||
int received = 0;
|
int received = 0;
|
||||||
if (total_len >= SCRATCH_BUFSIZE) {
|
if (total_len >= SCRATCH_BUFSIZE) {
|
||||||
/* Respond with 500 Internal Server Error */
|
/* Respond with 500 Internal Server Error */
|
||||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "content too long");
|
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "content too long");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
while (cur_len < total_len) {
|
while (cur_len < total_len) {
|
||||||
received = httpd_req_recv(req, buf + cur_len, total_len);
|
received = httpd_req_recv(req, buf + cur_len, total_len);
|
||||||
if (received <= 0) {
|
if (received <= 0) {
|
||||||
/* Respond with 500 Internal Server Error */
|
/* Respond with 500 Internal Server Error */
|
||||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to post control value");
|
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to post control value");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
cur_len += received;
|
cur_len += received;
|
||||||
}
|
}
|
||||||
buf[total_len] = '\0';
|
buf[total_len] = '\0';
|
||||||
ESP_LOGI(TAG, "buf=[%s]", buf);
|
ESP_LOGI(TAG, "buf=[%s]", buf);
|
||||||
|
|
||||||
|
|
||||||
bool parse = true;
|
bool parse = true;
|
||||||
cJSON *root = cJSON_Parse(buf);
|
cJSON *root = cJSON_Parse(buf);
|
||||||
|
|
||||||
// Search canid item
|
// Search canid item
|
||||||
int32_t canid = 0;
|
int32_t canid = 0;
|
||||||
cJSON* state = cJSON_GetObjectItem(root, "canid");
|
cJSON* state = cJSON_GetObjectItem(root, "canid");
|
||||||
if (state) {
|
if (state) {
|
||||||
canid = cJSON_GetObjectItem(root, "canid")->valueint;
|
canid = cJSON_GetObjectItem(root, "canid")->valueint;
|
||||||
ESP_LOGI(TAG, "canid=%"PRIx32, canid);
|
ESP_LOGI(TAG, "canid=%"PRIx32, canid);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "canid item not found");
|
ESP_LOGE(TAG, "canid item not found");
|
||||||
parse = false;
|
parse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search frame item
|
// Search frame item
|
||||||
char frameStr[12];
|
char frameStr[12];
|
||||||
uint16_t frame = 0;
|
uint16_t frame = 0;
|
||||||
state = cJSON_GetObjectItem(root, "frame");
|
state = cJSON_GetObjectItem(root, "frame");
|
||||||
if (state) {
|
if (state) {
|
||||||
strcpy(frameStr, cJSON_GetObjectItem(root,"frame")->valuestring);
|
strcpy(frameStr, cJSON_GetObjectItem(root,"frame")->valuestring);
|
||||||
ESP_LOGI(TAG, "frameStr=[%s]", frameStr);
|
ESP_LOGI(TAG, "frameStr=[%s]", frameStr);
|
||||||
if (strcmp(frameStr, "standard") != 0 && strcmp(frameStr, "extended") != 0 ) {
|
if (strcmp(frameStr, "standard") != 0 && strcmp(frameStr, "extended") != 0 ) {
|
||||||
ESP_LOGE(TAG, "frame item not correct");
|
ESP_LOGE(TAG, "frame item not correct");
|
||||||
parse = false;
|
parse = false;
|
||||||
} else {
|
} else {
|
||||||
if (strcmp(frameStr, "standard") == 0) frame = STANDARD_FRAME;
|
if (strcmp(frameStr, "standard") == 0) frame = STANDARD_FRAME;
|
||||||
if (strcmp(frameStr, "extended") == 0) frame = EXTENDED_FRAME;
|
if (strcmp(frameStr, "extended") == 0) frame = EXTENDED_FRAME;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "frame item not found");
|
ESP_LOGE(TAG, "frame item not found");
|
||||||
parse = false;
|
parse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search data item
|
// Search data item
|
||||||
int16_t data_len;
|
int16_t data_len;
|
||||||
char data_value[8];
|
char data_value[8];
|
||||||
state = cJSON_GetObjectItem(root, "data");
|
state = cJSON_GetObjectItem(root, "data");
|
||||||
if (state) {
|
if (state) {
|
||||||
cJSON *data_array = cJSON_GetObjectItem(root,"data");
|
cJSON *data_array = cJSON_GetObjectItem(root,"data");
|
||||||
ESP_LOGI(TAG, "data_array->type=%s", JSON_Types(data_array->type));
|
ESP_LOGI(TAG, "data_array->type=%s", JSON_Types(data_array->type));
|
||||||
if (data_array->type == cJSON_Array) {
|
if (data_array->type == cJSON_Array) {
|
||||||
int data_array_size = cJSON_GetArraySize(data_array);
|
int data_array_size = cJSON_GetArraySize(data_array);
|
||||||
ESP_LOGI(TAG, "data_array_size=%d", data_array_size);
|
ESP_LOGI(TAG, "data_array_size=%d", data_array_size);
|
||||||
bool data_valid = true;
|
bool data_valid = true;
|
||||||
data_len = data_array_size;
|
data_len = data_array_size;
|
||||||
if (data_array_size > 8) {
|
if (data_array_size > 8) {
|
||||||
ESP_LOGW(TAG, "Too many data arrays : %d", data_array_size);
|
ESP_LOGW(TAG, "Too many data arrays : %d", data_array_size);
|
||||||
data_len = 8;
|
data_len = 8;
|
||||||
}
|
}
|
||||||
for (int i=0;i<data_len;i++) {
|
for (int i=0;i<data_len;i++) {
|
||||||
cJSON *array = cJSON_GetArrayItem(data_array,i);
|
cJSON *array = cJSON_GetArrayItem(data_array,i);
|
||||||
//ESP_LOGI(TAG, "array->type=%s", JSON_Types(array->type));
|
//ESP_LOGI(TAG, "array->type=%s", JSON_Types(array->type));
|
||||||
uint16_t data_int = array->valueint;
|
uint16_t data_int = array->valueint;
|
||||||
ESP_LOGI(TAG, "data_int[%d]=%x", i, data_int);
|
ESP_LOGI(TAG, "data_int[%d]=%x", i, data_int);
|
||||||
if (data_int <= 0xff) {
|
if (data_int <= 0xff) {
|
||||||
data_value[i] = data_int;
|
data_value[i] = data_int;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "Too large data value : %x", data_int);
|
ESP_LOGE(TAG, "Too large data value : %x", data_int);
|
||||||
data_valid = false;
|
data_valid = false;
|
||||||
}
|
}
|
||||||
} // end for
|
} // end for
|
||||||
if (data_valid == false) {
|
if (data_valid == false) {
|
||||||
parse = false;
|
parse = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "data item not array");
|
ESP_LOGE(TAG, "data item not array");
|
||||||
parse = false;
|
parse = false;
|
||||||
} // end if
|
} // end if
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "data item not found");
|
ESP_LOGE(TAG, "data item not found");
|
||||||
parse = false;
|
parse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cJSON_Delete(root);
|
cJSON_Delete(root);
|
||||||
|
|
||||||
// JSON parse success. Send twai data.
|
// JSON parse success. Send twai data.
|
||||||
if (parse) {
|
if (parse) {
|
||||||
ESP_LOGI(TAG, "twai_send_handler frame=%d canid=%"PRIx32" data_len=%d", frame, canid, data_len);
|
ESP_LOGI(TAG, "twai_send_handler frame=%d canid=%"PRIx32" data_len=%d", frame, canid, data_len);
|
||||||
ESP_LOG_BUFFER_HEX(TAG, data_value, data_len);
|
ESP_LOG_BUFFER_HEX(TAG, data_value, data_len);
|
||||||
twai_message_t tx_msg;
|
twai_message_t tx_msg;
|
||||||
tx_msg.extd = frame;
|
tx_msg.extd = frame;
|
||||||
tx_msg.ss = 1;
|
tx_msg.ss = 1;
|
||||||
tx_msg.self = 0;
|
tx_msg.self = 0;
|
||||||
tx_msg.dlc_non_comp = 0;
|
tx_msg.dlc_non_comp = 0;
|
||||||
tx_msg.identifier = canid;
|
tx_msg.identifier = canid;
|
||||||
tx_msg.data_length_code = data_len;
|
tx_msg.data_length_code = data_len;
|
||||||
for (int i=0;i<data_len;i++) {
|
for (int i=0;i<data_len;i++) {
|
||||||
tx_msg.data[i] = data_value[i];
|
tx_msg.data[i] = data_value[i];
|
||||||
}
|
}
|
||||||
if (xQueueSend(xQueue_twai_tx, &tx_msg, portMAX_DELAY) != pdPASS) {
|
if (xQueueSend(xQueue_twai_tx, &tx_msg, portMAX_DELAY) != pdPASS) {
|
||||||
ESP_LOGE(TAG, "xQueueSend Fail");
|
ESP_LOGE(TAG, "xQueueSend Fail");
|
||||||
}
|
}
|
||||||
httpd_resp_sendstr(req, "CAN tx sent successfully");
|
httpd_resp_sendstr(req, "CAN tx sent successfully");
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "Request parameter not correct");
|
ESP_LOGE(TAG, "Request parameter not correct");
|
||||||
httpd_resp_sendstr(req, "Request parameter not correct");
|
httpd_resp_sendstr(req, "Request parameter not correct");
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function to start the file server */
|
/* Function to start the file server */
|
||||||
esp_err_t start_server(const char *base_path, int port)
|
esp_err_t start_server(const char *base_path, int port)
|
||||||
{
|
{
|
||||||
rest_server_context_t *rest_context = calloc(1, sizeof(rest_server_context_t));
|
rest_server_context_t *rest_context = calloc(1, sizeof(rest_server_context_t));
|
||||||
if (rest_context == NULL) {
|
if (rest_context == NULL) {
|
||||||
ESP_LOGE(TAG, "No memory for rest context");
|
ESP_LOGE(TAG, "No memory for rest context");
|
||||||
while(1) { vTaskDelay(1); }
|
while(1) { vTaskDelay(1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
httpd_handle_t server = NULL;
|
httpd_handle_t server = NULL;
|
||||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||||
config.server_port = port;
|
config.server_port = port;
|
||||||
|
|
||||||
/* Use the URI wildcard matching function in order to
|
/* Use the URI wildcard matching function in order to
|
||||||
* allow the same handler to respond to multiple different
|
* allow the same handler to respond to multiple different
|
||||||
* target URIs which match the wildcard scheme */
|
* target URIs which match the wildcard scheme */
|
||||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Starting HTTP Server on port: '%d'", config.server_port);
|
ESP_LOGD(TAG, "Starting HTTP Server on port: '%d'", config.server_port);
|
||||||
if (httpd_start(&server, &config) != ESP_OK) {
|
if (httpd_start(&server, &config) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to start file server!");
|
ESP_LOGE(TAG, "Failed to start file server!");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* URI handler for root */
|
/* URI handler for root */
|
||||||
httpd_uri_t root = {
|
httpd_uri_t root = {
|
||||||
.uri = "/", // Match all URIs of type /path/to/file
|
.uri = "/", // Match all URIs of type /path/to/file
|
||||||
.method = HTTP_GET,
|
.method = HTTP_GET,
|
||||||
.handler = root_get_handler,
|
.handler = root_get_handler,
|
||||||
//.user_ctx = server_data // Pass server data as context
|
//.user_ctx = server_data // Pass server data as context
|
||||||
};
|
};
|
||||||
httpd_register_uri_handler(server, &root);
|
httpd_register_uri_handler(server, &root);
|
||||||
|
|
||||||
/* URI handler for getting system info */
|
/* URI handler for getting system info */
|
||||||
httpd_uri_t system_info_get_uri = {
|
httpd_uri_t system_info_get_uri = {
|
||||||
.uri = "/api/system/info",
|
.uri = "/api/system/info",
|
||||||
.method = HTTP_GET,
|
.method = HTTP_GET,
|
||||||
.handler = system_info_get_handler,
|
.handler = system_info_get_handler,
|
||||||
.user_ctx = rest_context
|
.user_ctx = rest_context
|
||||||
};
|
};
|
||||||
httpd_register_uri_handler(server, &system_info_get_uri);
|
httpd_register_uri_handler(server, &system_info_get_uri);
|
||||||
|
|
||||||
/* URI handler for send twai */
|
/* URI handler for send twai */
|
||||||
httpd_uri_t twai_send_post_uri = {
|
httpd_uri_t twai_send_post_uri = {
|
||||||
.uri = "/api/twai/send",
|
.uri = "/api/twai/send",
|
||||||
.method = HTTP_POST,
|
.method = HTTP_POST,
|
||||||
.handler = twai_send_handler,
|
.handler = twai_send_handler,
|
||||||
.user_ctx = rest_context
|
.user_ctx = rest_context
|
||||||
};
|
};
|
||||||
httpd_register_uri_handler(server, &twai_send_post_uri);
|
httpd_register_uri_handler(server, &twai_send_post_uri);
|
||||||
|
|
||||||
/* URI handler for send twai */
|
/* URI handler for send twai */
|
||||||
httpd_uri_t twai_read = {
|
httpd_uri_t twai_read = {
|
||||||
.uri = "/api/twai/read",
|
.uri = "/api/twai/read",
|
||||||
.method = HTTP_GET,
|
.method = HTTP_GET,
|
||||||
.handler = twai_read_handler,
|
.handler = twai_read_handler,
|
||||||
//.user_ctx = rest_context
|
//.user_ctx = rest_context
|
||||||
};
|
};
|
||||||
httpd_register_uri_handler(server, &twai_read);
|
httpd_register_uri_handler(server, &twai_read);
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void http_server_task(void *pvParameters)
|
void http_server_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
char *task_parameter = (char *)pvParameters;
|
char *task_parameter = (char *)pvParameters;
|
||||||
ESP_LOGI(TAG, "Start task_parameter=%s", task_parameter);
|
ESP_LOGI(TAG, "Start task_parameter=%s", task_parameter);
|
||||||
char url[64];
|
char url[64];
|
||||||
sprintf(url, "http://%s:%d", task_parameter, CONFIG_WEB_PORT);
|
sprintf(url, "http://%s:%d", task_parameter, CONFIG_WEB_PORT);
|
||||||
ESP_LOGI(TAG, "Starting server on %s", url);
|
ESP_LOGI(TAG, "Starting server on %s", url);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Create Semaphore
|
// Create Semaphore
|
||||||
// This Semaphore is used for locking
|
// This Semaphore is used for locking
|
||||||
ctrl_task_sem = xSemaphoreCreateBinary();
|
ctrl_task_sem = xSemaphoreCreateBinary();
|
||||||
configASSERT( ctrl_task_sem );
|
configASSERT( ctrl_task_sem );
|
||||||
xSemaphoreGive(ctrl_task_sem);
|
xSemaphoreGive(ctrl_task_sem);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ESP_ERROR_CHECK(start_server("/spiffs", CONFIG_WEB_PORT));
|
ESP_ERROR_CHECK(start_server("/spiffs", CONFIG_WEB_PORT));
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
vTaskDelay(1);
|
vTaskDelay(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Never reach here
|
// Never reach here
|
||||||
ESP_LOGI(TAG, "finish");
|
ESP_LOGI(TAG, "finish");
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
## IDF Component Manager Manifest File
|
## IDF Component Manager Manifest File
|
||||||
dependencies:
|
dependencies:
|
||||||
espressif/mdns:
|
espressif/mdns:
|
||||||
version: "^1.0.3"
|
version: "^1.0.3"
|
||||||
rules:
|
rules:
|
||||||
- if: "idf_version >=5.0"
|
- if: "idf_version >=5.0"
|
||||||
|
|||||||
+7
-7
@@ -1,8 +1,8 @@
|
|||||||
#define MAX_FILE_SIZE_KB 10
|
#define MAX_FILE_SIZE_KB 10
|
||||||
#define MAX_TWAI_SIZE_KB 5
|
#define MAX_TWAI_SIZE_KB 5
|
||||||
#define MALLOCHI_TAG "INIT_MALLOCHI"
|
#define MALLOCHI_TAG "INIT_MALLOCHI"
|
||||||
|
|
||||||
char* file_read_buf;
|
char* file_read_buf;
|
||||||
char* twai_string_buf;
|
char* twai_string_buf;
|
||||||
int allocation_size;
|
int allocation_size;
|
||||||
int twai_allocation_size;
|
int twai_allocation_size;
|
||||||
+456
-456
@@ -1,456 +1,456 @@
|
|||||||
/*
|
/*
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
Unless required by applicable law or agreed to in writing, this
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/queue.h"
|
#include "freertos/queue.h"
|
||||||
#include "freertos/event_groups.h"
|
#include "freertos/event_groups.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_vfs.h"
|
#include "esp_vfs.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_spiffs.h"
|
#include "esp_spiffs.h"
|
||||||
#include "mdns.h"
|
#include "mdns.h"
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
#include "driver/twai.h" // Update from V4.2
|
#include "driver/twai.h" // Update from V4.2
|
||||||
#include "twai.h"
|
#include "twai.h"
|
||||||
#include "init_malloci.h"
|
#include "init_malloci.h"
|
||||||
#define TAG "MAIN"
|
#define TAG "MAIN"
|
||||||
|
|
||||||
static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
||||||
|
|
||||||
#if CONFIG_CAN_BITRATE_25
|
#if CONFIG_CAN_BITRATE_25
|
||||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_25KBITS();
|
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_25KBITS();
|
||||||
#define BITRATE "Bitrate is 25 Kbit/s"
|
#define BITRATE "Bitrate is 25 Kbit/s"
|
||||||
#elif CONFIG_CAN_BITRATE_50
|
#elif CONFIG_CAN_BITRATE_50
|
||||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_50KBITS();
|
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_50KBITS();
|
||||||
#define BITRATE "Bitrate is 50 Kbit/s"
|
#define BITRATE "Bitrate is 50 Kbit/s"
|
||||||
#elif CONFIG_CAN_BITRATE_100
|
#elif CONFIG_CAN_BITRATE_100
|
||||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_100KBITS();
|
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_100KBITS();
|
||||||
#define BITRATE "Bitrate is 100 Kbit/s"
|
#define BITRATE "Bitrate is 100 Kbit/s"
|
||||||
#elif CONFIG_CAN_BITRATE_125
|
#elif CONFIG_CAN_BITRATE_125
|
||||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_125KBITS();
|
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_125KBITS();
|
||||||
#define BITRATE "Bitrate is 125 Kbit/s"
|
#define BITRATE "Bitrate is 125 Kbit/s"
|
||||||
#elif CONFIG_CAN_BITRATE_250
|
#elif CONFIG_CAN_BITRATE_250
|
||||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS();
|
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS();
|
||||||
#define BITRATE "Bitrate is 250 Kbit/s"
|
#define BITRATE "Bitrate is 250 Kbit/s"
|
||||||
#elif CONFIG_CAN_BITRATE_500
|
#elif CONFIG_CAN_BITRATE_500
|
||||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
|
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
|
||||||
#define BITRATE "Bitrate is 500 Kbit/s"
|
#define BITRATE "Bitrate is 500 Kbit/s"
|
||||||
#elif CONFIG_CAN_BITRATE_800
|
#elif CONFIG_CAN_BITRATE_800
|
||||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_800KBITS();
|
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_800KBITS();
|
||||||
#define BITRATE "Bitrate is 800 Kbit/s"
|
#define BITRATE "Bitrate is 800 Kbit/s"
|
||||||
#elif CONFIG_CAN_BITRATE_1000
|
#elif CONFIG_CAN_BITRATE_1000
|
||||||
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_1MBITS();
|
static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_1MBITS();
|
||||||
#define BITRATE "Bitrate is 1 Mbit/s"
|
#define BITRATE "Bitrate is 1 Mbit/s"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* FreeRTOS event group to signal when we are connected*/
|
/* FreeRTOS event group to signal when we are connected*/
|
||||||
static EventGroupHandle_t s_wifi_event_group;
|
static EventGroupHandle_t s_wifi_event_group;
|
||||||
|
|
||||||
/* The event group allows multiple bits for each event, but we only care about two events:
|
/* The event group allows multiple bits for each event, but we only care about two events:
|
||||||
* - we are connected to the AP with an IP
|
* - we are connected to the AP with an IP
|
||||||
* - we failed to connect after the maximum amount of retries */
|
* - we failed to connect after the maximum amount of retries */
|
||||||
#define WIFI_CONNECTED_BIT BIT0
|
#define WIFI_CONNECTED_BIT BIT0
|
||||||
#define WIFI_FAIL_BIT BIT1
|
#define WIFI_FAIL_BIT BIT1
|
||||||
|
|
||||||
static int s_retry_num = 0;
|
static int s_retry_num = 0;
|
||||||
static char *base_path = "/spiffs";
|
static char *base_path = "/spiffs";
|
||||||
|
|
||||||
QueueHandle_t xQueue_http_client;
|
QueueHandle_t xQueue_http_client;
|
||||||
QueueHandle_t xQueue_twai_tx;
|
QueueHandle_t xQueue_twai_tx;
|
||||||
|
|
||||||
TOPIC_t *publish;
|
TOPIC_t *publish;
|
||||||
int16_t npublish;
|
int16_t npublish;
|
||||||
|
|
||||||
//extern char* twai_string_buf;
|
//extern char* twai_string_buf;
|
||||||
//extern esp_err_t init_twai_read_malloc();
|
//extern esp_err_t init_twai_read_malloc();
|
||||||
|
|
||||||
static void event_handler(void* arg, esp_event_base_t event_base,
|
static void event_handler(void* arg, esp_event_base_t event_base,
|
||||||
int32_t event_id, void* event_data)
|
int32_t event_id, void* event_data)
|
||||||
{
|
{
|
||||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||||
esp_wifi_connect();
|
esp_wifi_connect();
|
||||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||||
if (s_retry_num < CONFIG_ESP_MAXIMUM_RETRY) {
|
if (s_retry_num < CONFIG_ESP_MAXIMUM_RETRY) {
|
||||||
esp_wifi_connect();
|
esp_wifi_connect();
|
||||||
s_retry_num++;
|
s_retry_num++;
|
||||||
ESP_LOGI(TAG, "retry to connect to the AP");
|
ESP_LOGI(TAG, "retry to connect to the AP");
|
||||||
} else {
|
} else {
|
||||||
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG,"connect to the AP fail");
|
ESP_LOGI(TAG,"connect to the AP fail");
|
||||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
|
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
|
||||||
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||||
s_retry_num = 0;
|
s_retry_num = 0;
|
||||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wifi_init_sta()
|
void wifi_init_sta()
|
||||||
{
|
{
|
||||||
s_wifi_event_group = xEventGroupCreate();
|
s_wifi_event_group = xEventGroupCreate();
|
||||||
|
|
||||||
ESP_LOGI(TAG,"ESP-IDF Ver%d.%d", ESP_IDF_VERSION_MAJOR, ESP_IDF_VERSION_MINOR);
|
ESP_LOGI(TAG,"ESP-IDF Ver%d.%d", ESP_IDF_VERSION_MAJOR, ESP_IDF_VERSION_MINOR);
|
||||||
ESP_LOGI(TAG,"ESP_IDF_VERSION %d", ESP_IDF_VERSION);
|
ESP_LOGI(TAG,"ESP_IDF_VERSION %d", ESP_IDF_VERSION);
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_netif_init());
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
esp_netif_t *netif = esp_netif_create_default_wifi_sta();
|
esp_netif_t *netif = esp_netif_create_default_wifi_sta();
|
||||||
assert(netif);
|
assert(netif);
|
||||||
|
|
||||||
#if CONFIG_STATIC_IP
|
#if CONFIG_STATIC_IP
|
||||||
|
|
||||||
ESP_LOGI(TAG, "CONFIG_STATIC_IP_ADDRESS=[%s]",CONFIG_STATIC_IP_ADDRESS);
|
ESP_LOGI(TAG, "CONFIG_STATIC_IP_ADDRESS=[%s]",CONFIG_STATIC_IP_ADDRESS);
|
||||||
ESP_LOGI(TAG, "CONFIG_STATIC_GW_ADDRESS=[%s]",CONFIG_STATIC_GW_ADDRESS);
|
ESP_LOGI(TAG, "CONFIG_STATIC_GW_ADDRESS=[%s]",CONFIG_STATIC_GW_ADDRESS);
|
||||||
ESP_LOGI(TAG, "CONFIG_STATIC_NM_ADDRESS=[%s]",CONFIG_STATIC_NM_ADDRESS);
|
ESP_LOGI(TAG, "CONFIG_STATIC_NM_ADDRESS=[%s]",CONFIG_STATIC_NM_ADDRESS);
|
||||||
|
|
||||||
/* Stop DHCP client */
|
/* Stop DHCP client */
|
||||||
ESP_ERROR_CHECK(esp_netif_dhcpc_stop(netif));
|
ESP_ERROR_CHECK(esp_netif_dhcpc_stop(netif));
|
||||||
ESP_LOGI(TAG, "Stop DHCP Services");
|
ESP_LOGI(TAG, "Stop DHCP Services");
|
||||||
|
|
||||||
/* Set STATIC IP Address */
|
/* Set STATIC IP Address */
|
||||||
esp_netif_ip_info_t ip_info;
|
esp_netif_ip_info_t ip_info;
|
||||||
memset(&ip_info, 0 , sizeof(esp_netif_ip_info_t));
|
memset(&ip_info, 0 , sizeof(esp_netif_ip_info_t));
|
||||||
ip_info.ip.addr = ipaddr_addr(CONFIG_STATIC_IP_ADDRESS);
|
ip_info.ip.addr = ipaddr_addr(CONFIG_STATIC_IP_ADDRESS);
|
||||||
ip_info.netmask.addr = ipaddr_addr(CONFIG_STATIC_NM_ADDRESS);
|
ip_info.netmask.addr = ipaddr_addr(CONFIG_STATIC_NM_ADDRESS);
|
||||||
ip_info.gw.addr = ipaddr_addr(CONFIG_STATIC_GW_ADDRESS);;
|
ip_info.gw.addr = ipaddr_addr(CONFIG_STATIC_GW_ADDRESS);;
|
||||||
esp_netif_set_ip_info(netif, &ip_info);
|
esp_netif_set_ip_info(netif, &ip_info);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
I referred from here.
|
I referred from here.
|
||||||
https://www.esp32.com/viewtopic.php?t=5380
|
https://www.esp32.com/viewtopic.php?t=5380
|
||||||
if we should not be using DHCP (for example we are using static IP addresses),
|
if we should not be using DHCP (for example we are using static IP addresses),
|
||||||
then we need to instruct the ESP32 of the locations of the DNS servers manually.
|
then we need to instruct the ESP32 of the locations of the DNS servers manually.
|
||||||
Google publicly makes available two name servers with the addresses of 8.8.8.8 and 8.8.4.4.
|
Google publicly makes available two name servers with the addresses of 8.8.8.8 and 8.8.4.4.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ip_addr_t d;
|
ip_addr_t d;
|
||||||
d.type = IPADDR_TYPE_V4;
|
d.type = IPADDR_TYPE_V4;
|
||||||
d.u_addr.ip4.addr = 0x08080808; //8.8.8.8 dns
|
d.u_addr.ip4.addr = 0x08080808; //8.8.8.8 dns
|
||||||
dns_setserver(0, &d);
|
dns_setserver(0, &d);
|
||||||
d.u_addr.ip4.addr = 0x08080404; //8.8.4.4 dns
|
d.u_addr.ip4.addr = 0x08080404; //8.8.4.4 dns
|
||||||
dns_setserver(1, &d);
|
dns_setserver(1, &d);
|
||||||
|
|
||||||
#endif // CONFIG_STATIC_IP
|
#endif // CONFIG_STATIC_IP
|
||||||
|
|
||||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
||||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
|
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
|
||||||
|
|
||||||
wifi_config_t wifi_config = {
|
wifi_config_t wifi_config = {
|
||||||
.sta = {
|
.sta = {
|
||||||
.ssid = CONFIG_ESP_WIFI_SSID,
|
.ssid = CONFIG_ESP_WIFI_SSID,
|
||||||
.password = CONFIG_ESP_WIFI_PASSWORD
|
.password = CONFIG_ESP_WIFI_PASSWORD
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
|
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
|
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
|
||||||
ESP_ERROR_CHECK(esp_wifi_start() );
|
ESP_ERROR_CHECK(esp_wifi_start() );
|
||||||
|
|
||||||
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
||||||
|
|
||||||
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
|
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
|
||||||
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
|
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
|
||||||
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
|
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
|
||||||
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||||
pdFALSE,
|
pdFALSE,
|
||||||
pdFALSE,
|
pdFALSE,
|
||||||
portMAX_DELAY);
|
portMAX_DELAY);
|
||||||
|
|
||||||
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
|
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
|
||||||
* happened. */
|
* happened. */
|
||||||
if (bits & WIFI_CONNECTED_BIT) {
|
if (bits & WIFI_CONNECTED_BIT) {
|
||||||
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD);
|
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD);
|
||||||
} else if (bits & WIFI_FAIL_BIT) {
|
} else if (bits & WIFI_FAIL_BIT) {
|
||||||
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD);
|
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "UNEXPECTED EVENT");
|
ESP_LOGE(TAG, "UNEXPECTED EVENT");
|
||||||
}
|
}
|
||||||
vEventGroupDelete(s_wifi_event_group);
|
vEventGroupDelete(s_wifi_event_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialise_mdns(void)
|
void initialise_mdns(void)
|
||||||
{
|
{
|
||||||
//initialize mDNS
|
//initialize mDNS
|
||||||
ESP_ERROR_CHECK( mdns_init() );
|
ESP_ERROR_CHECK( mdns_init() );
|
||||||
//set mDNS hostname (required if you want to advertise services)
|
//set mDNS hostname (required if you want to advertise services)
|
||||||
ESP_ERROR_CHECK( mdns_hostname_set(CONFIG_MDNS_HOSTNAME) );
|
ESP_ERROR_CHECK( mdns_hostname_set(CONFIG_MDNS_HOSTNAME) );
|
||||||
ESP_LOGI(TAG, "mdns hostname set to: [%s]", CONFIG_MDNS_HOSTNAME);
|
ESP_LOGI(TAG, "mdns hostname set to: [%s]", CONFIG_MDNS_HOSTNAME);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
//set default mDNS instance name
|
//set default mDNS instance name
|
||||||
ESP_ERROR_CHECK( mdns_instance_name_set("ESP32 with mDNS") );
|
ESP_ERROR_CHECK( mdns_instance_name_set("ESP32 with mDNS") );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t mountSPIFFS(char * partition_label, char * base_path) {
|
esp_err_t mountSPIFFS(char * partition_label, char * base_path) {
|
||||||
ESP_LOGI(TAG, "Initializing SPIFFS file system");
|
ESP_LOGI(TAG, "Initializing SPIFFS file system");
|
||||||
|
|
||||||
esp_vfs_spiffs_conf_t conf = {
|
esp_vfs_spiffs_conf_t conf = {
|
||||||
.base_path = base_path,
|
.base_path = base_path,
|
||||||
.partition_label = partition_label,
|
.partition_label = partition_label,
|
||||||
.max_files = 4,
|
.max_files = 4,
|
||||||
.format_if_mount_failed = true
|
.format_if_mount_failed = true
|
||||||
};
|
};
|
||||||
// Use settings defined above to initialize and mount SPIFFS filesystem.
|
// Use settings defined above to initialize and mount SPIFFS filesystem.
|
||||||
// Note: esp_vfs_spiffs_register is an all-in-one convenience function.
|
// Note: esp_vfs_spiffs_register is an all-in-one convenience function.
|
||||||
esp_err_t ret = esp_vfs_spiffs_register(&conf);
|
esp_err_t ret = esp_vfs_spiffs_register(&conf);
|
||||||
|
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
if (ret == ESP_FAIL) {
|
if (ret == ESP_FAIL) {
|
||||||
ESP_LOGE(TAG, "Failed to mount or format filesystem");
|
ESP_LOGE(TAG, "Failed to mount or format filesystem");
|
||||||
} else if (ret == ESP_ERR_NOT_FOUND) {
|
} else if (ret == ESP_ERR_NOT_FOUND) {
|
||||||
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
|
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
|
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t total = 0, used = 0;
|
size_t total = 0, used = 0;
|
||||||
ret = esp_spiffs_info(partition_label, &total, &used);
|
ret = esp_spiffs_info(partition_label, &total, &used);
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
|
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
|
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
|
||||||
DIR* dir = opendir(base_path);
|
DIR* dir = opendir(base_path);
|
||||||
assert(dir != NULL);
|
assert(dir != NULL);
|
||||||
while (true) {
|
while (true) {
|
||||||
struct dirent*pe = readdir(dir);
|
struct dirent*pe = readdir(dir);
|
||||||
if (!pe) break;
|
if (!pe) break;
|
||||||
ESP_LOGI(TAG, "d_name=%s d_ino=%d d_type=%x", pe->d_name,pe->d_ino, pe->d_type);
|
ESP_LOGI(TAG, "d_name=%s d_ino=%d d_type=%x", pe->d_name,pe->d_ino, pe->d_type);
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "Mount SPIFFS filesystem");
|
ESP_LOGI(TAG, "Mount SPIFFS filesystem");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
esp_err_t build_table(TOPIC_t **topics, char *file, int16_t *ntopic)
|
esp_err_t build_table(TOPIC_t **topics, char *file, int16_t *ntopic)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "build_table file=%s", file);
|
ESP_LOGI(TAG, "build_table file=%s", file);
|
||||||
char line[128];
|
char line[128];
|
||||||
int _ntopic = 0;
|
int _ntopic = 0;
|
||||||
|
|
||||||
FILE* f = fopen(file, "r");
|
FILE* f = fopen(file, "r");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
ESP_LOGE(TAG, "Failed to open file for reading");
|
ESP_LOGE(TAG, "Failed to open file for reading");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
while (1){
|
while (1){
|
||||||
if ( fgets(line, sizeof(line) ,f) == 0 ) break;
|
if ( fgets(line, sizeof(line) ,f) == 0 ) break;
|
||||||
// strip newline
|
// strip newline
|
||||||
char* pos = strchr(line, '\n');
|
char* pos = strchr(line, '\n');
|
||||||
if (pos) {
|
if (pos) {
|
||||||
*pos = '\0';
|
*pos = '\0';
|
||||||
}
|
}
|
||||||
ESP_LOGD(TAG, "line=[%s]", line);
|
ESP_LOGD(TAG, "line=[%s]", line);
|
||||||
if (strlen(line) == 0) continue;
|
if (strlen(line) == 0) continue;
|
||||||
if (line[0] == '#') continue;
|
if (line[0] == '#') continue;
|
||||||
_ntopic++;
|
_ntopic++;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
ESP_LOGI(TAG, "build_table _ntopic=%d", _ntopic);
|
ESP_LOGI(TAG, "build_table _ntopic=%d", _ntopic);
|
||||||
|
|
||||||
*topics = calloc(_ntopic, sizeof(TOPIC_t));
|
*topics = calloc(_ntopic, sizeof(TOPIC_t));
|
||||||
if (*topics == NULL) {
|
if (*topics == NULL) {
|
||||||
ESP_LOGE(TAG, "Error allocating memory for topic");
|
ESP_LOGE(TAG, "Error allocating memory for topic");
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fopen(file, "r");
|
f = fopen(file, "r");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
ESP_LOGE(TAG, "Failed to open file for reading");
|
ESP_LOGE(TAG, "Failed to open file for reading");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (1){
|
while (1){
|
||||||
if ( fgets(line, sizeof(line) ,f) == 0 ) break;
|
if ( fgets(line, sizeof(line) ,f) == 0 ) break;
|
||||||
// strip newline
|
// strip newline
|
||||||
char* pos = strchr(line, '\n');
|
char* pos = strchr(line, '\n');
|
||||||
if (pos) {
|
if (pos) {
|
||||||
*pos = '\0';
|
*pos = '\0';
|
||||||
}
|
}
|
||||||
ESP_LOGD(TAG, "line=[%s]", line);
|
ESP_LOGD(TAG, "line=[%s]", line);
|
||||||
if (strlen(line) == 0) continue;
|
if (strlen(line) == 0) continue;
|
||||||
if (line[0] == '#') continue;
|
if (line[0] == '#') continue;
|
||||||
|
|
||||||
// Frame type
|
// Frame type
|
||||||
ptr = strtok(line, ",");
|
ptr = strtok(line, ",");
|
||||||
ESP_LOGD(TAG, "ptr=%s", ptr);
|
ESP_LOGD(TAG, "ptr=%s", ptr);
|
||||||
if (strcmp(ptr, "S") == 0) {
|
if (strcmp(ptr, "S") == 0) {
|
||||||
(*topics+index)->frame = 0;
|
(*topics+index)->frame = 0;
|
||||||
} else if (strcmp(ptr, "E") == 0) {
|
} else if (strcmp(ptr, "E") == 0) {
|
||||||
(*topics+index)->frame = 1;
|
(*topics+index)->frame = 1;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "This line is invalid [%s]", line);
|
ESP_LOGE(TAG, "This line is invalid [%s]", line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CAN ID
|
// CAN ID
|
||||||
uint32_t canid;
|
uint32_t canid;
|
||||||
ptr = strtok(NULL, ",");
|
ptr = strtok(NULL, ",");
|
||||||
if(ptr == NULL) continue;
|
if(ptr == NULL) continue;
|
||||||
ESP_LOGD(TAG, "ptr=%s", ptr);
|
ESP_LOGD(TAG, "ptr=%s", ptr);
|
||||||
canid = strtol(ptr, NULL, 16);
|
canid = strtol(ptr, NULL, 16);
|
||||||
if (canid == 0) {
|
if (canid == 0) {
|
||||||
ESP_LOGE(TAG, "This line is invalid [%s]", line);
|
ESP_LOGE(TAG, "This line is invalid [%s]", line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(*topics+index)->canid = canid;
|
(*topics+index)->canid = canid;
|
||||||
|
|
||||||
// mqtt topic
|
// mqtt topic
|
||||||
char *sp;
|
char *sp;
|
||||||
ptr = strtok(NULL, ",");
|
ptr = strtok(NULL, ",");
|
||||||
if(ptr == NULL) {
|
if(ptr == NULL) {
|
||||||
ESP_LOGE(TAG, "This line is invalid [%s]", line);
|
ESP_LOGE(TAG, "This line is invalid [%s]", line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ESP_LOGD(TAG, "ptr=[%s] strlen=%d", ptr, strlen(ptr));
|
ESP_LOGD(TAG, "ptr=[%s] strlen=%d", ptr, strlen(ptr));
|
||||||
sp = strstr(ptr,"#");
|
sp = strstr(ptr,"#");
|
||||||
if (sp != NULL) {
|
if (sp != NULL) {
|
||||||
ESP_LOGE(TAG, "This line is invalid [%s]", line);
|
ESP_LOGE(TAG, "This line is invalid [%s]", line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sp = strstr(ptr,"+");
|
sp = strstr(ptr,"+");
|
||||||
if (sp != NULL) {
|
if (sp != NULL) {
|
||||||
ESP_LOGE(TAG, "This line is invalid [%s]", line);
|
ESP_LOGE(TAG, "This line is invalid [%s]", line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
(*topics+index)->topic = (char *)malloc(strlen(ptr)+1);
|
(*topics+index)->topic = (char *)malloc(strlen(ptr)+1);
|
||||||
strcpy((*topics+index)->topic, ptr);
|
strcpy((*topics+index)->topic, ptr);
|
||||||
(*topics+index)->topic_len = strlen(ptr);
|
(*topics+index)->topic_len = strlen(ptr);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
*ntopic = index;
|
*ntopic = index;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_table(TOPIC_t *topics, int16_t ntopic)
|
void dump_table(TOPIC_t *topics, int16_t ntopic)
|
||||||
{
|
{
|
||||||
for(int i=0;i<ntopic;i++) {
|
for(int i=0;i<ntopic;i++) {
|
||||||
ESP_LOGI(pcTaskGetName(0), "topics=[%d] frame=%d canid=0x%"PRIx32" topic=[%s] topic_len=%d",
|
ESP_LOGI(pcTaskGetName(0), "topics=[%d] frame=%d canid=0x%"PRIx32" topic=[%s] topic_len=%d",
|
||||||
i, (topics+i)->frame, (topics+i)->canid, (topics+i)->topic, (topics+i)->topic_len);
|
i, (topics+i)->frame, (topics+i)->canid, (topics+i)->topic, (topics+i)->topic_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t init_file_malloc() {
|
esp_err_t init_file_malloc() {
|
||||||
allocation_size = (MAX_FILE_SIZE_KB*1024*sizeof(char));
|
allocation_size = (MAX_FILE_SIZE_KB*1024*sizeof(char));
|
||||||
file_read_buf = (char*)malloc(allocation_size);
|
file_read_buf = (char*)malloc(allocation_size);
|
||||||
|
|
||||||
if (file_read_buf == NULL) {
|
if (file_read_buf == NULL) {
|
||||||
ESP_LOGE(MALLOCHI_TAG, "File read memory not allocated.");
|
ESP_LOGE(MALLOCHI_TAG, "File read memory not allocated.");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(MALLOCHI_TAG, "File read malloc succeeded! %d bytes allocated", allocation_size);
|
ESP_LOGI(MALLOCHI_TAG, "File read malloc succeeded! %d bytes allocated", allocation_size);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t init_twai_read_malloc() {
|
esp_err_t init_twai_read_malloc() {
|
||||||
twai_allocation_size = (sizeof(char)*1024*MAX_TWAI_SIZE_KB);
|
twai_allocation_size = (sizeof(char)*1024*MAX_TWAI_SIZE_KB);
|
||||||
twai_string_buf = (char*)malloc(twai_allocation_size);
|
twai_string_buf = (char*)malloc(twai_allocation_size);
|
||||||
|
|
||||||
if (twai_string_buf == NULL) {
|
if (twai_string_buf == NULL) {
|
||||||
ESP_LOGE(MALLOCHI_TAG, "TWAI memory not allocated.");
|
ESP_LOGE(MALLOCHI_TAG, "TWAI memory not allocated.");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(MALLOCHI_TAG, "TWAI malloc succeeded! %d bytes allocated", twai_allocation_size);
|
ESP_LOGI(MALLOCHI_TAG, "TWAI malloc succeeded! %d bytes allocated", twai_allocation_size);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void http_client_task(void *pvParameters);
|
void http_client_task(void *pvParameters);
|
||||||
void http_server_task(void *pvParameters);
|
void http_server_task(void *pvParameters);
|
||||||
void twai_task(void *pvParameters);
|
void twai_task(void *pvParameters);
|
||||||
|
|
||||||
void app_main()
|
void app_main()
|
||||||
{
|
{
|
||||||
// Initialize NVS
|
// Initialize NVS
|
||||||
esp_err_t ret = nvs_flash_init();
|
esp_err_t ret = nvs_flash_init();
|
||||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
ret = nvs_flash_init();
|
ret = nvs_flash_init();
|
||||||
}
|
}
|
||||||
ESP_ERROR_CHECK(ret);
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
|
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
|
||||||
wifi_init_sta();
|
wifi_init_sta();
|
||||||
initialise_mdns();
|
initialise_mdns();
|
||||||
init_twai_read_malloc();
|
init_twai_read_malloc();
|
||||||
init_file_malloc();
|
init_file_malloc();
|
||||||
|
|
||||||
// Install and start TWAI driver
|
// Install and start TWAI driver
|
||||||
ESP_LOGI(TAG, "%s",BITRATE);
|
ESP_LOGI(TAG, "%s",BITRATE);
|
||||||
ESP_LOGI(TAG, "CTX_GPIO=%d",CONFIG_CTX_GPIO);
|
ESP_LOGI(TAG, "CTX_GPIO=%d",CONFIG_CTX_GPIO);
|
||||||
ESP_LOGI(TAG, "CRX_GPIO=%d",CONFIG_CRX_GPIO);
|
ESP_LOGI(TAG, "CRX_GPIO=%d",CONFIG_CRX_GPIO);
|
||||||
|
|
||||||
static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(CONFIG_CTX_GPIO, CONFIG_CRX_GPIO, TWAI_MODE_NORMAL);
|
static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(CONFIG_CTX_GPIO, CONFIG_CRX_GPIO, TWAI_MODE_NORMAL);
|
||||||
ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
|
ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
|
||||||
ESP_LOGI(TAG, "Driver installed");
|
ESP_LOGI(TAG, "Driver installed");
|
||||||
ESP_ERROR_CHECK(twai_start());
|
ESP_ERROR_CHECK(twai_start());
|
||||||
ESP_LOGI(TAG, "Driver started");
|
ESP_LOGI(TAG, "Driver started");
|
||||||
|
|
||||||
// Mount SPIFFS
|
// Mount SPIFFS
|
||||||
char *partition_label = "storage";
|
char *partition_label = "storage";
|
||||||
//char *base_path = "/spiffs";
|
//char *base_path = "/spiffs";
|
||||||
ret = mountSPIFFS(partition_label, base_path);
|
ret = mountSPIFFS(partition_label, base_path);
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "mountSPIFFS fail");
|
ESP_LOGE(TAG, "mountSPIFFS fail");
|
||||||
while(1) { vTaskDelay(1); }
|
while(1) { vTaskDelay(1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Queue
|
// Create Queue
|
||||||
xQueue_http_client = xQueueCreate( 10, sizeof(FRAME_t) );
|
xQueue_http_client = xQueueCreate( 10, sizeof(FRAME_t) );
|
||||||
configASSERT( xQueue_http_client );
|
configASSERT( xQueue_http_client );
|
||||||
xQueue_twai_tx = xQueueCreate( 10, sizeof(twai_message_t) );
|
xQueue_twai_tx = xQueueCreate( 10, sizeof(twai_message_t) );
|
||||||
configASSERT( xQueue_twai_tx );
|
configASSERT( xQueue_twai_tx );
|
||||||
|
|
||||||
// build publish table
|
// build publish table
|
||||||
ret = build_table(&publish, "/spiffs/can2http.csv", &npublish);
|
ret = build_table(&publish, "/spiffs/can2http.csv", &npublish);
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "build publish table fail");
|
ESP_LOGE(TAG, "build publish table fail");
|
||||||
while(1) { vTaskDelay(1); }
|
while(1) { vTaskDelay(1); }
|
||||||
}
|
}
|
||||||
dump_table(publish, npublish);
|
dump_table(publish, npublish);
|
||||||
|
|
||||||
/* Get the local IP address */
|
/* Get the local IP address */
|
||||||
//tcpip_adapter_ip_info_t ip_info;
|
//tcpip_adapter_ip_info_t ip_info;
|
||||||
//ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
|
//ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
|
||||||
esp_netif_ip_info_t ip_info;
|
esp_netif_ip_info_t ip_info;
|
||||||
ESP_ERROR_CHECK(esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ip_info));
|
ESP_ERROR_CHECK(esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ip_info));
|
||||||
|
|
||||||
char cparam0[64];
|
char cparam0[64];
|
||||||
//sprintf(cparam0, "%s", ip4addr_ntoa(&ip_info.ip));
|
//sprintf(cparam0, "%s", ip4addr_ntoa(&ip_info.ip));
|
||||||
sprintf(cparam0, IPSTR, IP2STR(&ip_info.ip));
|
sprintf(cparam0, IPSTR, IP2STR(&ip_info.ip));
|
||||||
xTaskCreate(http_server_task, "server", 1024*6, (void *)cparam0, 2, NULL);
|
xTaskCreate(http_server_task, "server", 1024*6, (void *)cparam0, 2, NULL);
|
||||||
|
|
||||||
xTaskCreate(http_client_task, "client", 1024*6, NULL, 2, NULL);
|
xTaskCreate(http_client_task, "client", 1024*6, NULL, 2, NULL);
|
||||||
xTaskCreate(twai_task, "twai_rx", 1024*6, NULL, 2, NULL);
|
xTaskCreate(twai_task, "twai_rx", 1024*6, NULL, 2, NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
+167
-167
@@ -1,167 +1,167 @@
|
|||||||
/* TWAI Network Example
|
/* TWAI Network Example
|
||||||
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
Unless required by applicable law or agreed to in writing, this
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/queue.h"
|
#include "freertos/queue.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "driver/twai.h" // Update from V4.2
|
#include "driver/twai.h" // Update from V4.2
|
||||||
#include "twai.h"
|
#include "twai.h"
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
//#include "init_malloci.h"
|
//#include "init_malloci.h"
|
||||||
|
|
||||||
static const char *TAG = "TWAI";
|
static const char *TAG = "TWAI";
|
||||||
|
|
||||||
extern QueueHandle_t xQueue_http_client;
|
extern QueueHandle_t xQueue_http_client;
|
||||||
extern QueueHandle_t xQueue_twai_tx;
|
extern QueueHandle_t xQueue_twai_tx;
|
||||||
|
|
||||||
extern TOPIC_t *publish;
|
extern TOPIC_t *publish;
|
||||||
extern int16_t npublish;
|
extern int16_t npublish;
|
||||||
int str_iterator = 0;
|
int str_iterator = 0;
|
||||||
extern char* twai_string_buf;
|
extern char* twai_string_buf;
|
||||||
|
|
||||||
//extern esp_err_t init_twai_read_malloc();
|
//extern esp_err_t init_twai_read_malloc();
|
||||||
|
|
||||||
void dump_table(TOPIC_t *topics, int16_t ntopic);
|
void dump_table(TOPIC_t *topics, int16_t ntopic);
|
||||||
|
|
||||||
void twai_task(void *pvParameters)
|
void twai_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG,"task start");
|
ESP_LOGI(TAG,"task start");
|
||||||
dump_table(publish, npublish);
|
dump_table(publish, npublish);
|
||||||
twai_message_t rx_msg;
|
twai_message_t rx_msg;
|
||||||
twai_message_t tx_msg;
|
twai_message_t tx_msg;
|
||||||
FRAME_t frameBuf;
|
FRAME_t frameBuf;
|
||||||
char* ftype;
|
char* ftype;
|
||||||
//char* fdata = (char*)malloc(32*sizeof(char));
|
//char* fdata = (char*)malloc(32*sizeof(char));
|
||||||
//int iterator = 0;
|
//int iterator = 0;
|
||||||
char flags[4];
|
char flags[4];
|
||||||
char identifier[4];
|
char identifier[4];
|
||||||
while (1) {
|
while (1) {
|
||||||
esp_err_t ret = twai_receive(&rx_msg, pdMS_TO_TICKS(10));
|
esp_err_t ret = twai_receive(&rx_msg, pdMS_TO_TICKS(10));
|
||||||
if (ret == ESP_OK) {
|
if (ret == ESP_OK) {
|
||||||
ESP_LOGD(TAG,"twai_receive identifier=0x%"PRIx32" flags=0x%"PRIx32" data_length_code=%d",
|
ESP_LOGD(TAG,"twai_receive identifier=0x%"PRIx32" flags=0x%"PRIx32" data_length_code=%d",
|
||||||
rx_msg.identifier, rx_msg.flags, rx_msg.data_length_code);
|
rx_msg.identifier, rx_msg.flags, rx_msg.data_length_code);
|
||||||
|
|
||||||
int ext = rx_msg.flags & 0x01;
|
int ext = rx_msg.flags & 0x01;
|
||||||
int rtr = rx_msg.flags & 0x02;
|
int rtr = rx_msg.flags & 0x02;
|
||||||
ESP_LOGD(TAG, "ext=%x rtr=%x", ext, rtr);
|
ESP_LOGD(TAG, "ext=%x rtr=%x", ext, rtr);
|
||||||
|
|
||||||
#if CONFIG_ENABLE_PRINT
|
#if CONFIG_ENABLE_PRINT
|
||||||
if (ext == STANDARD_FRAME) {
|
if (ext == STANDARD_FRAME) {
|
||||||
printf("Standard ID: 0x%03"PRIx32, rx_msg.identifier);
|
printf("Standard ID: 0x%03"PRIx32, rx_msg.identifier);
|
||||||
} else {
|
} else {
|
||||||
printf("Extended ID: 0x%08"PRIx32, rx_msg.identifier);
|
printf("Extended ID: 0x%08"PRIx32, rx_msg.identifier);
|
||||||
}
|
}
|
||||||
printf(" DLC: %d Data: ", rx_msg.data_length_code);
|
printf(" DLC: %d Data: ", rx_msg.data_length_code);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
#endif
|
#endif
|
||||||
// JSON fun fun fun output for da api
|
// JSON fun fun fun output for da api
|
||||||
if (ext == STANDARD_FRAME) {
|
if (ext == STANDARD_FRAME) {
|
||||||
ftype = "STANDARD_FRAME";
|
ftype = "STANDARD_FRAME";
|
||||||
} else {
|
} else {
|
||||||
ftype = "EXTENDED_FRAME";
|
ftype = "EXTENDED_FRAME";
|
||||||
}
|
}
|
||||||
|
|
||||||
cJSON *twai_root = cJSON_CreateObject();
|
cJSON *twai_root = cJSON_CreateObject();
|
||||||
|
|
||||||
int charslen_each = 6;
|
int charslen_each = 6;
|
||||||
int data_len_chars = rx_msg.data_length_code*charslen_each;
|
int data_len_chars = rx_msg.data_length_code*charslen_each;
|
||||||
char tmp_buf[charslen_each+2];
|
char tmp_buf[charslen_each+2];
|
||||||
char fdata[data_len_chars];
|
char fdata[data_len_chars];
|
||||||
|
|
||||||
if (rx_msg.data_length_code != 0) {
|
if (rx_msg.data_length_code != 0) {
|
||||||
for (int i = 0; i < rx_msg.data_length_code; i++) {
|
for (int i = 0; i < rx_msg.data_length_code; i++) {
|
||||||
snprintf(tmp_buf, charslen_each, "0x%02x ",rx_msg.data[i]);
|
snprintf(tmp_buf, charslen_each, "0x%02x ",rx_msg.data[i]);
|
||||||
strcat(fdata, tmp_buf);
|
strcat(fdata, tmp_buf);
|
||||||
}
|
}
|
||||||
fdata[strlen(fdata)-1] = '\0';
|
fdata[strlen(fdata)-1] = '\0';
|
||||||
cJSON_AddStringToObject(twai_root, "data", fdata);
|
cJSON_AddStringToObject(twai_root, "data", fdata);
|
||||||
}
|
}
|
||||||
snprintf(flags, sizeof(rx_msg.flags), "0x%"PRIx32, rx_msg.flags);
|
snprintf(flags, sizeof(rx_msg.flags), "0x%"PRIx32, rx_msg.flags);
|
||||||
snprintf(identifier, sizeof(rx_msg.identifier), "0x%"PRIx32, rx_msg.identifier);
|
snprintf(identifier, sizeof(rx_msg.identifier), "0x%"PRIx32, rx_msg.identifier);
|
||||||
|
|
||||||
cJSON_AddStringToObject(twai_root, "type", ftype);
|
cJSON_AddStringToObject(twai_root, "type", ftype);
|
||||||
cJSON_AddStringToObject(twai_root, "id", identifier);
|
cJSON_AddStringToObject(twai_root, "id", identifier);
|
||||||
cJSON_AddStringToObject(twai_root, "flags", flags);
|
cJSON_AddStringToObject(twai_root, "flags", flags);
|
||||||
cJSON_AddNumberToObject(twai_root, "ext", ext);
|
cJSON_AddNumberToObject(twai_root, "ext", ext);
|
||||||
cJSON_AddNumberToObject(twai_root, "rtr", rtr);
|
cJSON_AddNumberToObject(twai_root, "rtr", rtr);
|
||||||
cJSON_AddNumberToObject(twai_root, "dlc",rx_msg.data_length_code);
|
cJSON_AddNumberToObject(twai_root, "dlc",rx_msg.data_length_code);
|
||||||
|
|
||||||
char *string = cJSON_Print(twai_root);
|
char *string = cJSON_Print(twai_root);
|
||||||
char br[] = "<br>\n";
|
char br[] = "<br>\n";
|
||||||
|
|
||||||
strcat(twai_string_buf,string);
|
strcat(twai_string_buf,string);
|
||||||
strcat(twai_string_buf,br);
|
strcat(twai_string_buf,br);
|
||||||
|
|
||||||
cJSON_free(string);
|
cJSON_free(string);
|
||||||
cJSON_Delete(twai_root);
|
cJSON_Delete(twai_root);
|
||||||
// end json buffer funssss
|
// end json buffer funssss
|
||||||
|
|
||||||
for(int index=0;index<npublish;index++) {
|
for(int index=0;index<npublish;index++) {
|
||||||
if (publish[index].frame != ext) continue;
|
if (publish[index].frame != ext) continue;
|
||||||
if (publish[index].canid == rx_msg.identifier) {
|
if (publish[index].canid == rx_msg.identifier) {
|
||||||
ESP_LOGI(TAG, "publish[%d] frame=%d canid=0x%"PRIx32" topic=[%s] topic_len=%d",
|
ESP_LOGI(TAG, "publish[%d] frame=%d canid=0x%"PRIx32" topic=[%s] topic_len=%d",
|
||||||
index, publish[index].frame, publish[index].canid, publish[index].topic, publish[index].topic_len);
|
index, publish[index].frame, publish[index].canid, publish[index].topic, publish[index].topic_len);
|
||||||
strcpy(frameBuf.topic, publish[index].topic);
|
strcpy(frameBuf.topic, publish[index].topic);
|
||||||
frameBuf.command = CMD_RECEIVE;
|
frameBuf.command = CMD_RECEIVE;
|
||||||
frameBuf.topic_len = publish[index].topic_len;
|
frameBuf.topic_len = publish[index].topic_len;
|
||||||
frameBuf.canid = rx_msg.identifier;
|
frameBuf.canid = rx_msg.identifier;
|
||||||
frameBuf.ext = ext;
|
frameBuf.ext = ext;
|
||||||
frameBuf.rtr = rtr;
|
frameBuf.rtr = rtr;
|
||||||
if (rtr == 0) {
|
if (rtr == 0) {
|
||||||
frameBuf.data_len = rx_msg.data_length_code;
|
frameBuf.data_len = rx_msg.data_length_code;
|
||||||
} else {
|
} else {
|
||||||
frameBuf.data_len = 0;
|
frameBuf.data_len = 0;
|
||||||
}
|
}
|
||||||
for(int i=0;i<frameBuf.data_len;i++) {
|
for(int i=0;i<frameBuf.data_len;i++) {
|
||||||
frameBuf.data[i] = rx_msg.data[i];
|
frameBuf.data[i] = rx_msg.data[i];
|
||||||
}
|
}
|
||||||
if (xQueueSend(xQueue_http_client, &frameBuf, portMAX_DELAY) != pdPASS) {
|
if (xQueueSend(xQueue_http_client, &frameBuf, portMAX_DELAY) != pdPASS) {
|
||||||
ESP_LOGE(TAG, "xQueueSend Fail");
|
ESP_LOGE(TAG, "xQueueSend Fail");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (ret == ESP_ERR_TIMEOUT) {
|
} else if (ret == ESP_ERR_TIMEOUT) {
|
||||||
if (xQueueReceive(xQueue_twai_tx, &tx_msg, 0) == pdTRUE) {
|
if (xQueueReceive(xQueue_twai_tx, &tx_msg, 0) == pdTRUE) {
|
||||||
ESP_LOGI(TAG, "tx_msg.identifier=[0x%"PRIx32"] tx_msg.extd=%d", tx_msg.identifier, tx_msg.extd);
|
ESP_LOGI(TAG, "tx_msg.identifier=[0x%"PRIx32"] tx_msg.extd=%d", tx_msg.identifier, tx_msg.extd);
|
||||||
twai_status_info_t status_info;
|
twai_status_info_t status_info;
|
||||||
twai_get_status_info(&status_info);
|
twai_get_status_info(&status_info);
|
||||||
ESP_LOGD(TAG, "status_info.state=%d",status_info.state);
|
ESP_LOGD(TAG, "status_info.state=%d",status_info.state);
|
||||||
if (status_info.state != TWAI_STATE_RUNNING) {
|
if (status_info.state != TWAI_STATE_RUNNING) {
|
||||||
ESP_LOGE(TAG, "TWAI driver not running %d", status_info.state);
|
ESP_LOGE(TAG, "TWAI driver not running %d", status_info.state);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ESP_LOGD(TAG, "status_info.msgs_to_tx=%"PRIu32,status_info.msgs_to_tx);
|
ESP_LOGD(TAG, "status_info.msgs_to_tx=%"PRIu32,status_info.msgs_to_tx);
|
||||||
ESP_LOGD(TAG, "status_info.msgs_to_rx=%"PRIu32,status_info.msgs_to_rx);
|
ESP_LOGD(TAG, "status_info.msgs_to_rx=%"PRIu32,status_info.msgs_to_rx);
|
||||||
//esp_err_t ret = twai_transmit(&tx_msg, pdMS_TO_TICKS(10));
|
//esp_err_t ret = twai_transmit(&tx_msg, pdMS_TO_TICKS(10));
|
||||||
esp_err_t ret = twai_transmit(&tx_msg, 0);
|
esp_err_t ret = twai_transmit(&tx_msg, 0);
|
||||||
if (ret == ESP_OK) {
|
if (ret == ESP_OK) {
|
||||||
ESP_LOGI(TAG, "twai_transmit success");
|
ESP_LOGI(TAG, "twai_transmit success");
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "twai_transmit Fail %s", esp_err_to_name(ret));
|
ESP_LOGE(TAG, "twai_transmit Fail %s", esp_err_to_name(ret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "twai_receive Fail %s", esp_err_to_name(ret));
|
ESP_LOGE(TAG, "twai_receive Fail %s", esp_err_to_name(ret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Never reach here
|
// Never reach here
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-27
@@ -1,27 +1,27 @@
|
|||||||
#define STANDARD_FRAME 0
|
#define STANDARD_FRAME 0
|
||||||
#define EXTENDED_FRAME 1
|
#define EXTENDED_FRAME 1
|
||||||
|
|
||||||
#define DATA_FRAME 0
|
#define DATA_FRAME 0
|
||||||
#define REMOTE_FRAME 1
|
#define REMOTE_FRAME 1
|
||||||
|
|
||||||
#define CMD_RECEIVE 100
|
#define CMD_RECEIVE 100
|
||||||
#define CMD_SEND 200
|
#define CMD_SEND 200
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int16_t command;
|
int16_t command;
|
||||||
char topic[64];
|
char topic[64];
|
||||||
int16_t topic_len;
|
int16_t topic_len;
|
||||||
int32_t canid;
|
int32_t canid;
|
||||||
int16_t ext;
|
int16_t ext;
|
||||||
int16_t rtr;
|
int16_t rtr;
|
||||||
int16_t data_len;
|
int16_t data_len;
|
||||||
char data[8];
|
char data[8];
|
||||||
} FRAME_t;
|
} FRAME_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t frame;
|
uint16_t frame;
|
||||||
uint32_t canid;
|
uint32_t canid;
|
||||||
char * topic;
|
char * topic;
|
||||||
int16_t topic_len;
|
int16_t topic_len;
|
||||||
} TOPIC_t;
|
} TOPIC_t;
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -1,6 +1,6 @@
|
|||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
|
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
|
||||||
nvs, data, nvs, 0x9000, 0x6000,
|
nvs, data, nvs, 0x9000, 0x6000,
|
||||||
phy_init, data, phy, 0xf000, 0x1000,
|
phy_init, data, phy, 0xf000, 0x1000,
|
||||||
factory, app, factory, 0x10000, 2M,
|
factory, app, factory, 0x10000, 2M,
|
||||||
storage, data, spiffs, , 4M,
|
storage, data, spiffs, , 4M,
|
||||||
|
|||||||
|
@@ -1 +1 @@
|
|||||||
$Env:ESPPORT = "COM22"
|
$Env:ESPPORT = "COM22"
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
idf.py set-target esp32s3
|
idf.py set-target esp32s3
|
||||||
idf.py menuconfig
|
idf.py menuconfig
|
||||||
idf.py flash monitor
|
idf.py flash monitor
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
function Test-Delete {
|
function Test-Delete {
|
||||||
param (
|
param (
|
||||||
$file
|
$file
|
||||||
)
|
)
|
||||||
|
|
||||||
if (Test-Path $file) {
|
if (Test-Path $file) {
|
||||||
rm -r -fo $file
|
rm -r -fo $file
|
||||||
Write-Output "$file DELETED"
|
Write-Output "$file DELETED"
|
||||||
} else {
|
} else {
|
||||||
Write-Output "$file NOT present"
|
Write-Output "$file NOT present"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
idf.py erase-flash fullclean python-clean
|
idf.py erase-flash fullclean python-clean
|
||||||
|
|
||||||
Test-Delete -file .\managed_components
|
Test-Delete -file .\managed_components
|
||||||
Test-Delete -file .\build
|
Test-Delete -file .\build
|
||||||
Test-Delete -file .\sdkconfig.old
|
Test-Delete -file .\sdkconfig.old
|
||||||
Test-Delete -file .\dependencies.lock
|
Test-Delete -file .\dependencies.lock
|
||||||
Test-Delete -file .\sdkconfig.old
|
Test-Delete -file .\sdkconfig.old
|
||||||
|
|||||||
+23
-23
@@ -1,23 +1,23 @@
|
|||||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||||
# Espressif IoT Development Framework (ESP-IDF) 5.3.0 Project Minimal Configuration
|
# Espressif IoT Development Framework (ESP-IDF) 5.3.0 Project Minimal Configuration
|
||||||
#
|
#
|
||||||
CONFIG_IDF_TARGET="esp32s3"
|
CONFIG_IDF_TARGET="esp32s3"
|
||||||
CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC=y
|
CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC=y
|
||||||
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
|
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
|
||||||
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_ENABLE_PRINT=y
|
CONFIG_ENABLE_PRINT=y
|
||||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||||
CONFIG_HTTPD_PURGE_BUF_LEN=100
|
CONFIG_HTTPD_PURGE_BUF_LEN=100
|
||||||
CONFIG_SPIRAM=y
|
CONFIG_SPIRAM=y
|
||||||
CONFIG_SPIRAM_MODE_OCT=y
|
CONFIG_SPIRAM_MODE_OCT=y
|
||||||
CONFIG_SPIRAM_SPEED_80M=y
|
CONFIG_SPIRAM_SPEED_80M=y
|
||||||
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
|
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
|
||||||
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
||||||
CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB=y
|
CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB=y
|
||||||
CONFIG_ESP32S3_DATA_CACHE_64KB=y
|
CONFIG_ESP32S3_DATA_CACHE_64KB=y
|
||||||
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
|
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
|
||||||
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
|
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||||
# Espressif IoT Development Framework (ESP-IDF) 5.3.0 Project Minimal Configuration
|
# Espressif IoT Development Framework (ESP-IDF) 5.3.0 Project Minimal Configuration
|
||||||
#
|
#
|
||||||
CONFIG_IDF_TARGET="esp32s3"
|
CONFIG_IDF_TARGET="esp32s3"
|
||||||
CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC=y
|
CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC=y
|
||||||
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
|
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
|
||||||
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_ENABLE_PRINT=y
|
CONFIG_ENABLE_PRINT=y
|
||||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||||
CONFIG_HTTPD_PURGE_BUF_LEN=100
|
CONFIG_HTTPD_PURGE_BUF_LEN=100
|
||||||
CONFIG_SPIRAM=y
|
CONFIG_SPIRAM=y
|
||||||
CONFIG_SPIRAM_MODE_OCT=y
|
CONFIG_SPIRAM_MODE_OCT=y
|
||||||
CONFIG_SPIRAM_SPEED_80M=y
|
CONFIG_SPIRAM_SPEED_80M=y
|
||||||
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
|
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
|
||||||
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
||||||
CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB=y
|
CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB=y
|
||||||
CONFIG_ESP32S3_DATA_CACHE_64KB=y
|
CONFIG_ESP32S3_DATA_CACHE_64KB=y
|
||||||
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
|
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
|
||||||
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
|
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
|
||||||
|
|||||||
+88
-88
@@ -1,88 +1,88 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Simple REST Server
|
# Simple REST Server
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
import werkzeug
|
import werkzeug
|
||||||
import tornado.httpserver
|
import tornado.httpserver
|
||||||
import tornado.ioloop
|
import tornado.ioloop
|
||||||
import tornado.options
|
import tornado.options
|
||||||
import tornado.web
|
import tornado.web
|
||||||
|
|
||||||
from tornado.options import define, options
|
from tornado.options import define, options
|
||||||
define("port", default=8000, help="run on the given port", type=int)
|
define("port", default=8000, help="run on the given port", type=int)
|
||||||
define("lines", default=20, help="number of lines displayed", type=int)
|
define("lines", default=20, help="number of lines displayed", type=int)
|
||||||
|
|
||||||
database = []
|
database = []
|
||||||
|
|
||||||
class IndexHandler(tornado.web.RequestHandler):
|
class IndexHandler(tornado.web.RequestHandler):
|
||||||
def get(self):
|
def get(self):
|
||||||
global database
|
global database
|
||||||
items = []
|
items = []
|
||||||
for data in database:
|
for data in database:
|
||||||
#print("{}".format(data))
|
#print("{}".format(data))
|
||||||
datetime = data[0].split()
|
datetime = data[0].split()
|
||||||
#print("data={} datetime={}".format(data[0], datetime))
|
#print("data={} datetime={}".format(data[0], datetime))
|
||||||
|
|
||||||
items.append({
|
items.append({
|
||||||
"date": datetime[0],
|
"date": datetime[0],
|
||||||
"time": datetime[1],
|
"time": datetime[1],
|
||||||
"id": data[1],
|
"id": data[1],
|
||||||
"frame": data[2],
|
"frame": data[2],
|
||||||
"value": data[3]
|
"value": data[3]
|
||||||
})
|
})
|
||||||
#print("items={}".format(items))
|
#print("items={}".format(items))
|
||||||
self.render("index.html", lines=options.lines, items=items)
|
self.render("index.html", lines=options.lines, items=items)
|
||||||
|
|
||||||
#curl -X POST -H "Content-Type: application/json" -d '{"canid":101, "frame":"standard" , "data": [1,2,3,4,5,6,7,8]}' http://192.168.10.43:8000/post
|
#curl -X POST -H "Content-Type: application/json" -d '{"canid":101, "frame":"standard" , "data": [1,2,3,4,5,6,7,8]}' http://192.168.10.43:8000/post
|
||||||
class PostHandler(tornado.web.RequestHandler):
|
class PostHandler(tornado.web.RequestHandler):
|
||||||
def post(self):
|
def post(self):
|
||||||
#print("{}".format(self.request.body))
|
#print("{}".format(self.request.body))
|
||||||
function = sys._getframe().f_code.co_name
|
function = sys._getframe().f_code.co_name
|
||||||
dict = tornado.escape.json_decode(self.request.body)
|
dict = tornado.escape.json_decode(self.request.body)
|
||||||
print("{} dict={}".format(function, dict))
|
print("{} dict={}".format(function, dict))
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
items.append(now.strftime("%Y/%m/%d %H:%M:%S"))
|
items.append(now.strftime("%Y/%m/%d %H:%M:%S"))
|
||||||
if ("canid" in dict):
|
if ("canid" in dict):
|
||||||
print("{} canid=0x{:x}".format(function, dict['canid']))
|
print("{} canid=0x{:x}".format(function, dict['canid']))
|
||||||
items.append(dict['canid'])
|
items.append(dict['canid'])
|
||||||
|
|
||||||
if ("frame" in dict):
|
if ("frame" in dict):
|
||||||
print("{} frame={}".format(function, dict['frame']))
|
print("{} frame={}".format(function, dict['frame']))
|
||||||
items.append(dict['frame'])
|
items.append(dict['frame'])
|
||||||
|
|
||||||
if ("data" in dict):
|
if ("data" in dict):
|
||||||
print("{} data length={}".format(function, len(dict['data'])))
|
print("{} data length={}".format(function, len(dict['data'])))
|
||||||
print("{} data={}".format(function, dict['data']))
|
print("{} data={}".format(function, dict['data']))
|
||||||
items.append(dict['data'])
|
items.append(dict['data'])
|
||||||
|
|
||||||
global database
|
global database
|
||||||
#print("{} {} {}".format(type(database), len(database), database))
|
#print("{} {} {}".format(type(database), len(database), database))
|
||||||
print("lines={}".format(options.lines))
|
print("lines={}".format(options.lines))
|
||||||
#if(len(database) >= 20):
|
#if(len(database) >= 20):
|
||||||
if(len(database) >= options.lines):
|
if(len(database) >= options.lines):
|
||||||
database.pop(0)
|
database.pop(0)
|
||||||
database.append(items)
|
database.append(items)
|
||||||
|
|
||||||
self.write(json.dumps({"result":"ok"}))
|
self.write(json.dumps({"result":"ok"}))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
tornado.options.parse_command_line()
|
tornado.options.parse_command_line()
|
||||||
print("port={}".format(options.port))
|
print("port={}".format(options.port))
|
||||||
print("lines={}".format(options.lines))
|
print("lines={}".format(options.lines))
|
||||||
app = tornado.web.Application(
|
app = tornado.web.Application(
|
||||||
handlers=[
|
handlers=[
|
||||||
(r"/", IndexHandler),
|
(r"/", IndexHandler),
|
||||||
(r"/post", PostHandler),
|
(r"/post", PostHandler),
|
||||||
],
|
],
|
||||||
template_path=os.path.join(os.getcwd(), "templates"),
|
template_path=os.path.join(os.getcwd(), "templates"),
|
||||||
debug=True
|
debug=True
|
||||||
)
|
)
|
||||||
http_server = tornado.httpserver.HTTPServer(app)
|
http_server = tornado.httpserver.HTTPServer(app)
|
||||||
http_server.listen(options.port)
|
http_server.listen(options.port)
|
||||||
tornado.ioloop.IOLoop.current().start()
|
tornado.ioloop.IOLoop.current().start()
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
<meta http-equiv="refresh" content="5;url="/">
|
<meta http-equiv="refresh" content="5;url="/">
|
||||||
<title>CAN DATA</title>
|
<title>CAN DATA</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
Display the latest {{ lines }} records.<br>
|
Display the latest {{ lines }} records.<br>
|
||||||
If you want to see more, specify the number of lines at startup.<br>
|
If you want to see more, specify the number of lines at startup.<br>
|
||||||
|
|
||||||
<table border="1" cellpadding="2" cellspacing="2">
|
<table border="1" cellpadding="2" cellspacing="2">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr style="color:#ffffff;" bgcolor="#800000">
|
<tr style="color:#ffffff;" bgcolor="#800000">
|
||||||
<th valign="top">Date</th>
|
<th valign="top">Date</th>
|
||||||
<th valign="top">Time</th>
|
<th valign="top">Time</th>
|
||||||
<th valign="top">ID</th>
|
<th valign="top">ID</th>
|
||||||
<th valign="top">Frame</th>
|
<th valign="top">Frame</th>
|
||||||
<th valign="top">Value</th>
|
<th valign="top">Value</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% for i in items %}
|
{% for i in items %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ i['date'] }}</td>
|
<td>{{ i['date'] }}</td>
|
||||||
<td>{{ i['time'] }}</td>
|
<td>{{ i['time'] }}</td>
|
||||||
<td>{{ i['id'] }}</td>
|
<td>{{ i['id'] }}</td>
|
||||||
<td>{{ i['frame'] }}</td>
|
<td>{{ i['frame'] }}</td>
|
||||||
<td>{{ i['value'] }}</td>
|
<td>{{ i['value'] }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% end %}
|
{% end %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user