Git Product home page Git Product logo

mqtt-rs's Introduction

MQTT-rs

Build Status Build & Test License crates.io dependency status

MQTT protocol library for Rust

[dependencies]
mqtt-protocol = "0.12"

Usage

extern crate mqtt;

use std::io::Cursor;

use mqtt::{Encodable, Decodable};
use mqtt::packet::{VariablePacket, PublishPacket, QoSWithPacketIdentifier};
use mqtt::TopicName;

fn main() {
    // Create a new Publish packet
    let packet = PublishPacket::new(TopicName::new("mqtt/learning").unwrap(),
                                    QoSWithPacketIdentifier::Level2(10),
                                    "Hello MQTT!");

    // Encode
    let mut buf = Vec::new();
    packet.encode(&mut buf).unwrap();
    println!("Encoded: {:?}", buf);

    // Decode it with known type
    let mut dec_buf = Cursor::new(&buf[..]);
    let decoded = PublishPacket::decode(&mut dec_buf).unwrap();
    println!("Decoded: {:?}", decoded);
    assert_eq!(packet, decoded);

    // Auto decode by the fixed header
    let mut dec_buf = Cursor::new(&buf[..]);
    let auto_decode = VariablePacket::decode(&mut dec_buf).unwrap();
    println!("Variable packet decode: {:?}", auto_decode);
    assert_eq!(VariablePacket::PublishPacket(packet), auto_decode);
}

Note

mqtt-rs's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mqtt-rs's Issues

glad to see mqtt in rust.

I am interested in mqtt recently. It's very lucky to see this, especially in rust.
I am still learning, but would like to do some contribution here.

Unable to decode disconnect packet

I've added conn.set_keep_alive(5); to sub-client example and broker is disconnecting as expected if there is no message exchange within keep_alive time

1458943648: Client /MQTT/rust/e2603b7b64714a2bb198a054c08e9f68 has exceeded timeout, disconnecting.

I expect broker to be sending disconnect packet at this point and to verify this I added below lines in the 2nd loop

&VariablePacket::DisconnectPacket(..) => {
                error!("Received disconnect packet from broker");
                break;
            }

But unfortunately, this condition isn't getting hit and I'm stuck with infinite loop of below error here

ERROR:sub_client: Error in receiving packet unexpected EOF
ERROR:sub_client: Error in receiving packet unexpected EOF
ERROR:sub_client: Error in receiving packet unexpected EOF

TopicName and TopicFilter should provide some way of accessing the internal String

This one bit me while trying to write a mock server, and trying to construct a fake PublishPacket given a SubscribePacket. I was going to extract the underlying String, replace any wildcard characters with mock strings, create a new TopicName from that, and then issue a Publish. But there doesn't seem to be any way to access the owned String.

Basically I need a get_str(&self) method or something similar on TopicFilter that returns a &str. For symmetry we should also provide an accessor for TopicName's String. Does this approach sound OK to you?

rustfmt.toml is broken on stable

Trying to format using current stable (Rust 1.47.0 and rustfmt 1.4.20-stable) produces the following:

Warning: Unknown configuration option `chain_indent`
Warning: Unknown configuration option `fn_call_style`
Warning: Unknown configuration option `fn_call_width`
Warning: Unknown configuration option `reorder_imported_names`
Warning: Unknown configuration option `reorder_imports_in_group`
Error: Decoding config file failed:
unknown variant `Visual`, expected one of `Compressed`, `Tall`, `Vertical` for key `fn_args_layout`
Please check your config file.

In general, rustfmt should work without errors or warnings on stable, and we should avoid committing formatting configs that require nightly.

Time for a new release?

Hi! We would like to use the latest version of the code with regex dependency removed. Cargo bloat indicates that it takes like 600KB of binary size on our architecture. We'd like to have only crates.io dependencies. Any plans for a new release soon?

BR Karl

Publish Packet Length

Hello, I am not sure but I think I might have found a bug.

The encodable_packet! macro, seems to be generating a packet length implementation that may not be taking into account the length of a topic name.

here is a test repo that will assert the error.

Maybe I am misunderstanding but it seems like the post-header packet data

[
// length of 5 (2 bytes)
0, 5,
// "topic" (5 bytes)
116, 111, 112, 105, 99,
// packet  id "1" (2 bytes)
0, 1
]

would have a second byte of 9 (5 + 2 + 2) but when I create that packet I get 7 for the second byte.

Error in sub-client example

Command:

cargo run --example sub-client -- -h test.mosquitto.org:1883 -s \#

Part of the error messages:

PUBLISH (owntracks/selvarossa/iphone): {"t":"b","tst":1468189183,"acc":65,"_type":"location","alt":521,"lon":11.04108761259167,"vac":10,"p":95.58914184570312,"lat":46.65532086320265,"batt":85,"tid":"NE"}
PUBLISH (owntracks/busware/iPhone): {"t":"c","tst":1468170121,"acc":65,"_type":"location","alt":18,"lon":10.67634490017904,"vac":10,"lat":54.04545819017535,"batt":49,"tid":"DT"}
PUBLISH (owntracks/dambrosio-clock/marissa): {"tst":1468191419,"acc":65,"_type":"location","alt":56,"lon":-73.34709625757841,"vac":56,"lat":40.82209127719133,"batt":73,"tid":"ME"}
PUBLISH (owntracks/dambrosio-clock/eric): {"tst":1468191443,"acc":65,"_type":"location","alt":41,"lon":-73.64894811083626,"vac":24,"lat":40.85203848541637,"batt":99,"tid":"EC"}
PUBLISH (owntracks/markus/aneta): {"_type": "location", "lat": "60.3994487", "lon": "5.3203096", "tst": "1468184591", "acc": "98.56"}
PUBLISH (owntracks/user/powermikee): {"t":"u","tst":1468214207,"acc":165,"_type":"location","alt":17,"lon":153.3893834218882,"vac":19,"p":101.5056686401367,"lat":-27.9805143762423,"batt":34,"tid":"1"}
PUBLISH (PL/production/weather): {"direction": 3, "temperature": 210, "humidity": 770, "stationId": "cms1", "rainfallCurrent": 0, "time": 1468215788, "rainfallHour": 0, "speed": 10}
ERROR:sub_client: Error in receiving packet Invalid topic filter (devices/02817be0/$online)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishComplete (0x4)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishComplete (0x5)
ERROR:sub_client: Error in receiving packet Invalid topic filter (devices/02817be0/$nodes)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0xC)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x7)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishComplete (0x4)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishComplete (0x3)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x9)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x3)
ERROR:sub_client: Error in receiving packet Invalid topic filter (devices/02817be0/$name)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishComplete (0x4)
ERROR:sub_client: Error in receiving packet Invalid flag for ConnectAcknowledgement (0x9)
ERROR:sub_client: Error in receiving packet Invalid flag for Connect (0x9)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x5)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x9)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x5)
ERROR:sub_client: Error in receiving packet Invalid flag for ConnectAcknowledgement (0xF)
ERROR:sub_client: Error in receiving packet Malformed data
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x1)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x5)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0xF)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x5)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishComplete (0x2)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0xC)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishComplete (0x9)
ERROR:sub_client: Error in receiving packet Invalid flag for ConnectAcknowledgement (0x2)
ERROR:sub_client: Error in receiving packet Invalid flag for Connect (0xB)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x5)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x9)
ERROR:sub_client: Error in receiving packet Invalid flag for PublishRelease (0x5)
ERROR:sub_client: Error in receiving packet Invalid flag for ConnectAcknowledgement (0xF)
ERROR:sub_client: Error in receiving packet Malformed data

A performanсe when publishing many packets to the same topic

Hi!
As I see, for publish a packet from client - I must:

  1. Make a topic String (or string slice) - contains own copy of data in heap
  2. Make a TopicName which "eats" topic String (or copies string to own copy in heap) and checks it with RegExp
  3. Make a payload - also own copy in heap
  4. Make a PublishPacket which "eats" TopicName and payload
  5. Serialize the packet to stream, which does not "eat" packet
  6. Drop the packet

When I need (and many others probaly too) to publish different (millions by day) payloads to the same (thousands) topics -
i can't reuse TopicName for doing 1-2 steps once and doing only 3-6 steps for every publish.

Also i can't store a packet for later reuse - it does not support payload replacing.

So this architecture breaks performance.

If You can add ability for using in packet shared ref to TopicName (and for payload may be too, but it
is not important) - it will be great!

Or add convenience fn which receives &TopicName, payload: &[u8], &mut Vec
and serializes 1st and 2nd arguments to 3rd...

Yuri

Add support for non-blocking sockets

Currently mqtt-rs doesn't handle non-blocking sockets properly - it doesn't provide any special handling for IO errors where ErrorKind == WouldBlock (or Interrupted)), even though such errors are part of the std::io::Read and std::io::Write APIs.

I work around this issue by setting my own buffers between mqtt-rs and the actual network socket, so mqtt-rs always decodes from and encodes to the in-memory buffers, and the network I/O is handled externally.

Adding support for non-blocking sockets would be non-trivial, but a very welcomed feature.

High level implementation

I'm implementing higher level functions on top of you library here. I intend to push these here eventually if you are OK with it.

Example sub-client-async is broken.

./target/debug/examples/mqtt_sub -S 192.168.0.18:1883 -s test/topic
[2022-02-22T06:37:39Z INFO  mqtt_sub] Connecting to "192.168.0.18:1883" ...
[2022-02-22T06:37:39Z INFO  mqtt_sub] Connected!
[2022-02-22T06:37:39Z INFO  mqtt_sub] Client identifier "/MQTT/rust/f3573265-523d-4eaf-a890-e189fb17fef4"
[2022-02-22T06:37:39Z INFO  mqtt_sub] Applying channel filters [(TopicFilter("test/topic"), Level0)] ...
[2022-02-22T06:37:39Z INFO  mqtt_sub] Subscribed!
[2022-02-22T06:37:39Z INFO  mqtt_sub] Sending PINGREQ to broker
[2022-02-22T06:37:39Z INFO  mqtt_sub] Receiving PINGRESP from broker ..
[2022-02-22T06:38:01Z INFO  mqtt_sub] Sending PINGREQ to broker
[2022-02-22T06:38:01Z INFO  mqtt_sub] Sending PINGREQ to broker
[2022-02-22T06:38:01Z INFO  mqtt_sub] Sending PINGREQ to broker
[2022-02-22T06:38:01Z INFO  mqtt_sub] Sending PINGREQ to broker
[2022-02-22T06:38:04Z INFO  mqtt_sub] Sending PINGREQ to broker
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 32, kind: BrokenPipe, message: "Broken pipe" }', examples/mqtt_sub.rs:160:46
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

rustc 1.58.1 (db9d1b20b 2022-01-20)

New to this project, it seems the pinger task is interrupted by the other task.

suggestion to improve readability of enum QualityOfService

Can the enum QualityOfService be updated as like below?
pub enum QualityOfService {
Level_0 = 0,
Level_1 = 1,
Level_2 = 2,
}

I read the current enum as "level 10" and was puzzled for a bit.
since the last l in level looks a lot like "1".

[docs] subscriber example

Hi, I see there isn't much in the way of docs yet.

It would be good to have a quick example of subscriber implementation.

Thanks!

Packets should derive Clone

Self-explanatory. I'm writing some tokio code right now that needs to take ownership of a PublishPacket to send it in a Future. I need to clone the packet before sending, in case I need to resend with DUP set. Should be as simple as adding Clone to the #[derive(...)] fields for each struct, and the VariablePacket enum.

Getting the `std::io::Error` underlying a `mqtt::Packet::VariablePacketError` is more cumbersome than it should be.

When decoding network bytes into any kind of protocol, even if your error handling strategy is to simply panic, you'll typically want to handle at least the "incomplete packet, need more bytes" error cleanly (by trying again when more data arrived).

I initially handled this by matching the Result of VariablePacket::decode() against VariablePacketError::IoError(ref e) if e.kind() == ErrorKind::UnexpectedEof, but it turns out that the IoError variant can actually end up deeper inside other VariablePacketError variants, depending on how much has been parsed so far.

My current workaround is this (pseudo-code) :

fn to_io_error(e: VariablePacketError) -> std::io::Error {
    match e {
        VariablePacketError::FixedHeaderError(FixedHeaderError::IoError(i))
        | VariablePacketError::IoError(i)
        | VariablePacketError::ConnectPacketError(PacketError::IoError(i))
        | VariablePacketError::ConnackPacketError(PacketError::IoError(i))
        | VariablePacketError::PublishPacketError(PacketError::IoError(i))
        | VariablePacketError::PubackPacketError(PacketError::IoError(i))
        | VariablePacketError::PubrecPacketError(PacketError::IoError(i))
        | VariablePacketError::PubrelPacketError(PacketError::IoError(i))
        | VariablePacketError::PubcompPacketError(PacketError::IoError(i))
        | VariablePacketError::PingreqPacketError(PacketError::IoError(i))
        | VariablePacketError::PingrespPacketError(PacketError::IoError(i))
        | VariablePacketError::SubscribePacketError(PacketError::IoError(i))
        | VariablePacketError::SubackPacketError(PacketError::IoError(i))
        | VariablePacketError::UnsubscribePacketError(PacketError::IoError(i))
        | VariablePacketError::UnsubackPacketError(PacketError::IoError(i))
        | VariablePacketError::DisconnectPacketError(PacketError::IoError(i)) => i,
        _ => std::io::Error::new(ErrorKind::InvalidData, e),
    }
}
pub struct MqttCodec;
impl tokio::codec::Decoder for MqttCodec {
    type Item = VariablePacket;
    type Error = std::io::Error;
    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        match VariablePacket::decode(src) {
            Ok(vp) => Ok(Some(vp)),
            Err(vperr) => {
                let ioerr = to_io_error(vperr);
                match ioerr.kind() {
                    ErrorKind::UnexpectedEof => Ok(None),
                    _ => Err(ioerr),
                }
            },
        }
    }
}

It works for my current unit tests, but:

  • It's surprising and ugly
  • It doesn't handle any deeper cases, like VariablePaketError -> PacketError -> VariableHeaderError -> TopicNameError -> StringEncodeError- > IoError (!)
  • It could easily bitrot if new enum variants are added.

Maybe there's a better technique ?

I see a few different ways to fix this (and can devote some time towards a PR):

  • Make sure that any io::Error bubbles up to the topmost mqtt error type, so the user never has to dig. That's the least-surprising option, I guess it could be implemented by tweaking all the From<SubError> for TopError impls, and we could still retain the deepest error inside .source().
  • Implement From<AnyMqttErrorType> for std::io::Error. This is basically a clean version of my workaround, might be useful in other cases, but users might still be surprised that matching on TopMostMqttError::IoError doesn't catch all cases.
  • Implement AnyMqttError::io_error() -> Option<Error>. Meh.
  • Combine these options and change the error types, for example by always returning an std::io::Error with the mqtt-specific issues in source(). Tempting, but a breaking change and it'll take a while to figure out.

Thanks in advance.

Slash is not allowed in topic name

Hi.

The standard's 4.7.1.1 says:

Topic level separators can appear anywhere in a Topic Filter or Topic Name

But the regexp doesn't allow it and TopicName::new fails.

Also the regexps for TopicName and TopicFilter could be compiled only once using lazy_static! to avoid compiling them each time strings are compared.

Unable to connect mqtt servere in adafruit.io

Initially it was showing server request and unable to connect so I have uncommented the debug comment in the adfruit library.But now I am getting this

# CODE

`/***************************************************
Adafruit MQTT Library ESP8266 Example

Must use ESP8266 Arduino from:
https://github.com/esp8266/Arduino

Works great with Adafruit's Huzzah ESP board & Feather
----> https://www.adafruit.com/product/2471
----> https://www.adafruit.com/products/2821

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

Written by Tony DiCola for Adafruit Industries.
MIT license, all text above must be included in any redistribution
#define DEBUG_PRINT 0

void setup() {
if (DEBUG_PRINT) {
Serial.begin(115200);
}
}
****************************************************/
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

/************************* WiFi Access Point *********************************/

#define WLAN_SSID "Labhansh Photography"
#define WLAN_PASS "thakkar69"

/************************* Adafruit.io Setup *********************************/

#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883 // use 8883 for SSL
#define AIO_USERNAME "Drboy"
#define AIO_KEY

"71dafd72b0f64863d2c02ba3f6d9c"

/************ Global State (you don't need to change this!) ******************/

// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

/****************************** Feeds ***************************************/

// Setup a feed called 'photocell' for publishing.
// Notice MQTT paths for AIO follow the form: /feeds/
Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/photocell");

// Setup a feed called 'onoff' for subscribing to changes.
Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/onoff");

/*************************** Sketch Code ************************************/

// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();

void setup() {
Serial.begin(115200);
delay(10);

Serial.println(F("Adafruit MQTT demo"));

// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);

WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();

Serial.println("WiFi connected");
Serial.println("IP address: "); Serial.println(WiFi.localIP());

// Setup MQTT subscription for onoff feed.
mqtt.subscribe(&onoffbutton);
}

uint32_t x=0;

void loop() {
// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();

// this is our 'wait for incoming subscription packets' busy subloop
// try to spend your time here

Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(5000))) {
if (subscription == &onoffbutton) {
Serial.print(F("Got: "));
Serial.println((char *)onoffbutton.lastread);
}
}

// Now we can publish stuff!
Serial.print(F("\nSending photocell val "));
Serial.print(x);
Serial.print("...");
if (! photocell.publish(x++)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}

// ping the server to keep the mqtt connection alive
// NOT required if you are publishing once every KEEPALIVE seconds
/*
if(! mqtt.ping()) {
mqtt.disconnect();
}
*/
}

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;

// Stop if already connected.
if (mqtt.connected()) {
return;
}

Serial.print("Connecting to MQTT... ");

uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1);
}
}
Serial.println("MQTT Connected!");
}

SERIAL MONITOR OUTPUT

Connecting to Labhansh Photography
...
WiFi connected
IP address:
192.168.31.190
Added sub 0
Connecting to MQTT... Connecting to: io.adafruit.com
Connect result: 0
Connection failed
Retrying MQTT connection in 5 seconds...
MQTT disconnect packet:
⸮ [0xE0], [0x00],
Connection failed!
Unable to send disconnect packet
Connecting to: io.adafruit.com
Connect result: 0
Connection failed
Retrying MQTT connection in 5 seconds...
MQTT disconnect packet:
⸮ [0xE0], [0x00],
Connection failed!
Unable to send disconnect packet
Connecting to: io.adafruit.com
Connect result: 0
Connection failed
Retrying MQTT connection in 5 seconds...
MQTT disconnect packet:
⸮ [0xE0], [0x00],
Connection failed!
Unable to send disconnect packet

Soft WDT reset

ctx: cont
sp: 3ffef600 end: 3ffef7f0 offset: 01b0

stack>>>
3ffef7b0: 00000001 3ffee5b8 3ffee794 40201e1e
3ffef7c0: 3fffdad0 00000000 3ffee7b8 40201e74
3ffef7d0: 3fffdad0 00000000 3ffee7b8 40203d54
3ffef7e0: feefeffe feefeffe 3ffee7d0 40100718
<<<stack<<<

ets Jan 8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v3ffe864c
~ld
⸮Adafruit MQTT demo

## **ESP exception decoder output for stacks**

Decoding 4 results
0x40201e1e: MQTT_connect() at C:\Users\piyus\OneDrive\Documents\Arduino\MCU_4/MCU_4.ino line 150
0x40201e74: loop at C:\Users\piyus\OneDrive\Documents\Arduino\MCU_4/MCU_4.ino line 105
0x40203d54: loop_wrapper at C:\Users\piyus\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/core_esp8266_main.cpp line 56
0x40100718: cont_norm at C:\Users\piyus\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/cont.S line 109

`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.