mirror of https://github.com/arendst/Tasmota.git
Update PubSubClient lib
Replaced PubSubClient library by EspEasy patched non-blocking version saving some 3k5 code space over arduino-mqtt library
This commit is contained in:
parent
ae28a50dc7
commit
04493965e4
|
@ -1,39 +0,0 @@
|
|||
import unittest
|
||||
import settings
|
||||
import time
|
||||
import mosquitto
|
||||
|
||||
|
||||
def on_message(mosq, obj, msg):
|
||||
obj.message_queue.append(msg)
|
||||
|
||||
|
||||
class mqtt_basic(unittest.TestCase):
|
||||
|
||||
message_queue = []
|
||||
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self)
|
||||
self.client.connect(settings.server_ip)
|
||||
self.client.on_message = on_message
|
||||
self.client.subscribe("outTopic", 0)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(self):
|
||||
self.client.disconnect()
|
||||
|
||||
def test_one(self):
|
||||
i = 30
|
||||
while len(self.message_queue) == 0 and i > 0:
|
||||
self.client.loop()
|
||||
time.sleep(0.5)
|
||||
i -= 1
|
||||
self.assertTrue(i > 0, "message receive timed-out")
|
||||
self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received")
|
||||
msg = self.message_queue[0]
|
||||
self.assertEqual(msg.mid, 0, "message id not 0")
|
||||
self.assertEqual(msg.topic, "outTopic", "message topic incorrect")
|
||||
self.assertEqual(msg.payload, "hello world")
|
||||
self.assertEqual(msg.qos, 0, "message qos not 0")
|
||||
self.assertEqual(msg.retain, False, "message retain flag incorrect")
|
|
@ -1,59 +0,0 @@
|
|||
import unittest
|
||||
import settings
|
||||
import time
|
||||
import mosquitto
|
||||
|
||||
|
||||
def on_message(mosq, obj, msg):
|
||||
obj.message_queue.append(msg)
|
||||
|
||||
|
||||
class mqtt_publish_in_callback(unittest.TestCase):
|
||||
|
||||
message_queue = []
|
||||
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self)
|
||||
self.client.connect(settings.server_ip)
|
||||
self.client.on_message = on_message
|
||||
self.client.subscribe("outTopic", 0)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(self):
|
||||
self.client.disconnect()
|
||||
|
||||
def test_connect(self):
|
||||
i = 30
|
||||
while len(self.message_queue) == 0 and i > 0:
|
||||
self.client.loop()
|
||||
time.sleep(0.5)
|
||||
i -= 1
|
||||
self.assertTrue(i > 0, "message receive timed-out")
|
||||
self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received")
|
||||
msg = self.message_queue.pop(0)
|
||||
self.assertEqual(msg.mid, 0, "message id not 0")
|
||||
self.assertEqual(msg.topic, "outTopic", "message topic incorrect")
|
||||
self.assertEqual(msg.payload, "hello world")
|
||||
self.assertEqual(msg.qos, 0, "message qos not 0")
|
||||
self.assertEqual(msg.retain, False, "message retain flag incorrect")
|
||||
|
||||
def test_publish(self):
|
||||
self.assertEqual(len(self.message_queue), 0, "message queue not empty")
|
||||
payload = "abcdefghij"
|
||||
self.client.publish("inTopic", payload)
|
||||
|
||||
i = 30
|
||||
while len(self.message_queue) == 0 and i > 0:
|
||||
self.client.loop()
|
||||
time.sleep(0.5)
|
||||
i -= 1
|
||||
|
||||
self.assertTrue(i > 0, "message receive timed-out")
|
||||
self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received")
|
||||
msg = self.message_queue.pop(0)
|
||||
self.assertEqual(msg.mid, 0, "message id not 0")
|
||||
self.assertEqual(msg.topic, "outTopic", "message topic incorrect")
|
||||
self.assertEqual(msg.payload, payload)
|
||||
self.assertEqual(msg.qos, 0, "message qos not 0")
|
||||
self.assertEqual(msg.retain, False, "message retain flag incorrect")
|
|
@ -1,181 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import shutil
|
||||
from subprocess import call
|
||||
import importlib
|
||||
import unittest
|
||||
import re
|
||||
|
||||
from testcases import settings
|
||||
|
||||
|
||||
class Workspace(object):
|
||||
|
||||
def __init__(self):
|
||||
self.root_dir = os.getcwd()
|
||||
self.build_dir = os.path.join(self.root_dir, "tmpbin")
|
||||
self.log_dir = os.path.join(self.root_dir, "logs")
|
||||
self.tests_dir = os.path.join(self.root_dir, "testcases")
|
||||
self.examples_dir = os.path.join(self.root_dir, "../PubSubClient/examples")
|
||||
self.examples = []
|
||||
self.tests = []
|
||||
if not os.path.isdir("../PubSubClient"):
|
||||
raise Exception("Cannot find PubSubClient library")
|
||||
try:
|
||||
return __import__('ino')
|
||||
except ImportError:
|
||||
raise Exception("ino tool not installed")
|
||||
|
||||
def init(self):
|
||||
if os.path.isdir(self.build_dir):
|
||||
shutil.rmtree(self.build_dir)
|
||||
os.mkdir(self.build_dir)
|
||||
if os.path.isdir(self.log_dir):
|
||||
shutil.rmtree(self.log_dir)
|
||||
os.mkdir(self.log_dir)
|
||||
|
||||
os.chdir(self.build_dir)
|
||||
call(["ino", "init"])
|
||||
|
||||
shutil.copytree("../../PubSubClient", "lib/PubSubClient")
|
||||
|
||||
filenames = []
|
||||
for root, dirs, files in os.walk(self.examples_dir):
|
||||
filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")]
|
||||
filenames.sort()
|
||||
for e in filenames:
|
||||
self.examples.append(Sketch(self, e))
|
||||
|
||||
filenames = []
|
||||
for root, dirs, files in os.walk(self.tests_dir):
|
||||
filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")]
|
||||
filenames.sort()
|
||||
for e in filenames:
|
||||
self.tests.append(Sketch(self, e))
|
||||
|
||||
def clean(self):
|
||||
shutil.rmtree(self.build_dir)
|
||||
|
||||
|
||||
class Sketch(object):
|
||||
def __init__(self, wksp, fn):
|
||||
self.w = wksp
|
||||
self.filename = fn
|
||||
self.basename = os.path.basename(self.filename)
|
||||
self.build_log = os.path.join(self.w.log_dir, "%s.log" % (os.path.basename(self.filename),))
|
||||
self.build_err_log = os.path.join(self.w.log_dir, "%s.err.log" % (os.path.basename(self.filename),))
|
||||
self.build_upload_log = os.path.join(self.w.log_dir, "%s.upload.log" % (os.path.basename(self.filename),))
|
||||
|
||||
def build(self):
|
||||
sys.stdout.write(" Build: ")
|
||||
sys.stdout.flush()
|
||||
|
||||
# Copy sketch over, replacing IP addresses as necessary
|
||||
fin = open(self.filename, "r")
|
||||
lines = fin.readlines()
|
||||
fin.close()
|
||||
fout = open(os.path.join(self.w.build_dir, "src", "sketch.ino"), "w")
|
||||
for l in lines:
|
||||
if re.match(r"^byte server\[\] = {", l):
|
||||
fout.write("byte server[] = { %s };\n" % (settings.server_ip.replace(".", ", "),))
|
||||
elif re.match(r"^byte ip\[\] = {", l):
|
||||
fout.write("byte ip[] = { %s };\n" % (settings.arduino_ip.replace(".", ", "),))
|
||||
else:
|
||||
fout.write(l)
|
||||
fout.flush()
|
||||
fout.close()
|
||||
|
||||
# Run build
|
||||
fout = open(self.build_log, "w")
|
||||
ferr = open(self.build_err_log, "w")
|
||||
rc = call(["ino", "build"], stdout=fout, stderr=ferr)
|
||||
fout.close()
|
||||
ferr.close()
|
||||
if rc == 0:
|
||||
sys.stdout.write("pass")
|
||||
sys.stdout.write("\n")
|
||||
return True
|
||||
else:
|
||||
sys.stdout.write("fail")
|
||||
sys.stdout.write("\n")
|
||||
with open(self.build_err_log) as f:
|
||||
for line in f:
|
||||
print(" " + line)
|
||||
return False
|
||||
|
||||
def upload(self):
|
||||
sys.stdout.write(" Upload: ")
|
||||
sys.stdout.flush()
|
||||
fout = open(self.build_upload_log, "w")
|
||||
rc = call(["ino", "upload"], stdout=fout, stderr=fout)
|
||||
fout.close()
|
||||
if rc == 0:
|
||||
sys.stdout.write("pass")
|
||||
sys.stdout.write("\n")
|
||||
return True
|
||||
else:
|
||||
sys.stdout.write("fail")
|
||||
sys.stdout.write("\n")
|
||||
with open(self.build_upload_log) as f:
|
||||
for line in f:
|
||||
print(" " + line)
|
||||
return False
|
||||
|
||||
def test(self):
|
||||
# import the matching test case, if it exists
|
||||
try:
|
||||
basename = os.path.basename(self.filename)[:-4]
|
||||
i = importlib.import_module("testcases." + basename)
|
||||
except:
|
||||
sys.stdout.write(" Test: no tests found")
|
||||
sys.stdout.write("\n")
|
||||
return
|
||||
c = getattr(i, basename)
|
||||
|
||||
testmethods = [m for m in dir(c) if m.startswith("test_")]
|
||||
testmethods.sort()
|
||||
tests = []
|
||||
for m in testmethods:
|
||||
tests.append(c(m))
|
||||
|
||||
result = unittest.TestResult()
|
||||
c.setUpClass()
|
||||
if self.upload():
|
||||
sys.stdout.write(" Test: ")
|
||||
sys.stdout.flush()
|
||||
for t in tests:
|
||||
t.run(result)
|
||||
print(str(result.testsRun - len(result.failures) - len(result.errors)) + "/" + str(result.testsRun))
|
||||
if not result.wasSuccessful():
|
||||
if len(result.failures) > 0:
|
||||
for f in result.failures:
|
||||
print("-- " + str(f[0]))
|
||||
print(f[1])
|
||||
if len(result.errors) > 0:
|
||||
print(" Errors:")
|
||||
for f in result.errors:
|
||||
print("-- " + str(f[0]))
|
||||
print(f[1])
|
||||
c.tearDownClass()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_tests = True
|
||||
|
||||
w = Workspace()
|
||||
w.init()
|
||||
|
||||
for e in w.examples:
|
||||
print("--------------------------------------")
|
||||
print("[" + e.basename + "]")
|
||||
if e.build() and run_tests:
|
||||
e.test()
|
||||
for e in w.tests:
|
||||
print("--------------------------------------")
|
||||
print("[" + e.basename + "]")
|
||||
if e.build() and run_tests:
|
||||
e.test()
|
||||
|
||||
w.clean()
|
|
@ -38,6 +38,14 @@ long lastMsg = 0;
|
|||
char msg[50];
|
||||
int value = 0;
|
||||
|
||||
void setup() {
|
||||
pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
|
||||
Serial.begin(115200);
|
||||
setup_wifi();
|
||||
client.setServer(mqtt_server, 1883);
|
||||
client.setCallback(callback);
|
||||
}
|
||||
|
||||
void setup_wifi() {
|
||||
|
||||
delay(10);
|
||||
|
@ -53,8 +61,6 @@ void setup_wifi() {
|
|||
Serial.print(".");
|
||||
}
|
||||
|
||||
randomSeed(micros());
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
|
@ -85,11 +91,8 @@ void reconnect() {
|
|||
// Loop until we're reconnected
|
||||
while (!client.connected()) {
|
||||
Serial.print("Attempting MQTT connection...");
|
||||
// Create a random client ID
|
||||
String clientId = "ESP8266Client-";
|
||||
clientId += String(random(0xffff), HEX);
|
||||
// Attempt to connect
|
||||
if (client.connect(clientId.c_str())) {
|
||||
if (client.connect("ESP8266Client")) {
|
||||
Serial.println("connected");
|
||||
// Once connected, publish an announcement...
|
||||
client.publish("outTopic", "hello world");
|
||||
|
@ -104,15 +107,6 @@ void reconnect() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
|
||||
Serial.begin(115200);
|
||||
setup_wifi();
|
||||
client.setServer(mqtt_server, 1883);
|
||||
client.setCallback(callback);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
if (!client.connected()) {
|
|
@ -117,8 +117,8 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass
|
|||
if (!connected()) {
|
||||
int result = 0;
|
||||
|
||||
if (domain != NULL) {
|
||||
result = _client->connect(this->domain, this->port);
|
||||
if (domain.length() != 0) {
|
||||
result = _client->connect(this->domain.c_str(), this->port);
|
||||
} else {
|
||||
result = _client->connect(this->ip, this->port);
|
||||
}
|
||||
|
@ -209,7 +209,6 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass
|
|||
boolean PubSubClient::readByte(uint8_t * result) {
|
||||
uint32_t previousMillis = millis();
|
||||
while(!_client->available()) {
|
||||
delay(1); // Add esp8266 de-blocking (Tasmota #790)
|
||||
uint32_t currentMillis = millis();
|
||||
if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){
|
||||
return false;
|
||||
|
@ -241,11 +240,17 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
|
|||
uint8_t start = 0;
|
||||
|
||||
do {
|
||||
if (len == 6) {
|
||||
// Invalid remaining length encoding - kill the connection
|
||||
_state = MQTT_DISCONNECTED;
|
||||
_client->stop();
|
||||
return 0;
|
||||
}
|
||||
if(!readByte(&digit)) return 0;
|
||||
buffer[len++] = digit;
|
||||
length += (digit & 127) * multiplier;
|
||||
multiplier *= 128;
|
||||
} while ((digit & 128) != 0);
|
||||
} while ((digit & 128) != 0 && len < (MQTT_MAX_PACKET_SIZE -2));
|
||||
*lengthLength = len-1;
|
||||
|
||||
if (isPublish) {
|
||||
|
@ -336,6 +341,9 @@ boolean PubSubClient::loop() {
|
|||
} else if (type == MQTTPINGRESP) {
|
||||
pingOutstanding = false;
|
||||
}
|
||||
} else if (!connected()) {
|
||||
// readPacket has closed the connection
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -419,7 +427,7 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig
|
|||
|
||||
lastOutActivity = millis();
|
||||
|
||||
return rc == tlen + 4 + plength;
|
||||
return rc == tlen + 3 + llen + plength;
|
||||
}
|
||||
|
||||
boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) {
|
||||
|
@ -469,7 +477,7 @@ boolean PubSubClient::subscribe(const char* topic) {
|
|||
}
|
||||
|
||||
boolean PubSubClient::subscribe(const char* topic, uint8_t qos) {
|
||||
if (qos < 0 || qos > 1) {
|
||||
if (qos > 1) {
|
||||
return false;
|
||||
}
|
||||
if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
|
||||
|
@ -524,7 +532,7 @@ uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t po
|
|||
const char* idp = string;
|
||||
uint16_t i = 0;
|
||||
pos += 2;
|
||||
while (*idp) {
|
||||
while (*idp && pos < (MQTT_MAX_PACKET_SIZE - 2)) {
|
||||
buf[pos++] = *idp++;
|
||||
i++;
|
||||
}
|
||||
|
@ -559,7 +567,7 @@ PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) {
|
|||
PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) {
|
||||
this->ip = ip;
|
||||
this->port = port;
|
||||
this->domain = NULL;
|
||||
this->domain = "";
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -24,13 +24,13 @@
|
|||
// MQTT_MAX_PACKET_SIZE : Maximum packet size
|
||||
#ifndef MQTT_MAX_PACKET_SIZE
|
||||
//#define MQTT_MAX_PACKET_SIZE 128
|
||||
//#define MQTT_MAX_PACKET_SIZE 512 // Tasmota
|
||||
#define MQTT_MAX_PACKET_SIZE 1000 // Tasmota v5.11.1c
|
||||
#endif
|
||||
|
||||
// MQTT_KEEPALIVE : keepAlive interval in Seconds
|
||||
// Keepalive timeout for default MQTT Broker is 10s
|
||||
#ifndef MQTT_KEEPALIVE
|
||||
#define MQTT_KEEPALIVE 15
|
||||
#define MQTT_KEEPALIVE 10
|
||||
#endif
|
||||
|
||||
// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds
|
||||
|
@ -75,7 +75,7 @@
|
|||
#define MQTTQOS1 (1 << 1)
|
||||
#define MQTTQOS2 (2 << 1)
|
||||
|
||||
#ifdef ESP8266
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
#include <functional>
|
||||
#define MQTT_CALLBACK_SIGNATURE std::function<void(char*, uint8_t*, unsigned int)> callback
|
||||
#else
|
||||
|
@ -97,7 +97,7 @@ private:
|
|||
boolean write(uint8_t header, uint8_t* buf, uint16_t length);
|
||||
uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos);
|
||||
IPAddress ip;
|
||||
const char* domain;
|
||||
String domain;
|
||||
uint16_t port;
|
||||
Stream* stream;
|
||||
int _state;
|
||||
|
@ -116,6 +116,7 @@ public:
|
|||
PubSubClient(const char*, uint16_t, Client& client, Stream&);
|
||||
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
|
||||
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&);
|
||||
virtual ~PubSubClient() {}
|
||||
|
||||
PubSubClient& setServer(IPAddress ip, uint16_t port);
|
||||
PubSubClient& setServer(uint8_t * ip, uint16_t port);
|
|
@ -133,23 +133,6 @@ int test_connect_accepts_username_no_password() {
|
|||
|
||||
END_IT
|
||||
}
|
||||
int test_connect_accepts_username_blank_password() {
|
||||
IT("accepts a username and blank password");
|
||||
ShimClient shimClient;
|
||||
shimClient.setAllowConnect(true);
|
||||
|
||||
byte connect[] = { 0x10,0x20,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xc2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x0};
|
||||
byte connack[] = { 0x20, 0x02, 0x00, 0x00 };
|
||||
shimClient.expect(connect,0x26);
|
||||
shimClient.respond(connack,4);
|
||||
|
||||
PubSubClient client(server, 1883, callback, shimClient);
|
||||
int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"pass");
|
||||
IS_TRUE(rc);
|
||||
IS_FALSE(shimClient.error());
|
||||
|
||||
END_IT
|
||||
}
|
||||
|
||||
int test_connect_ignores_password_no_username() {
|
||||
IT("ignores a password but no username");
|
|
@ -2,13 +2,9 @@
|
|||
#include "Arduino.h"
|
||||
|
||||
Buffer::Buffer() {
|
||||
this->pos = 0;
|
||||
this->length = 0;
|
||||
}
|
||||
|
||||
Buffer::Buffer(uint8_t* buf, size_t size) {
|
||||
this->pos = 0;
|
||||
this->length = 0;
|
||||
this->add(buf,size);
|
||||
}
|
||||
bool Buffer::available() {
|
|
@ -0,0 +1,43 @@
|
|||
import unittest
|
||||
import settings
|
||||
|
||||
import time
|
||||
import mosquitto
|
||||
|
||||
import serial
|
||||
|
||||
def on_message(mosq, obj, msg):
|
||||
obj.message_queue.append(msg)
|
||||
|
||||
class mqtt_basic(unittest.TestCase):
|
||||
|
||||
message_queue = []
|
||||
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self)
|
||||
self.client.connect(settings.server_ip)
|
||||
self.client.on_message = on_message
|
||||
self.client.subscribe("outTopic",0)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(self):
|
||||
self.client.disconnect()
|
||||
|
||||
def test_one(self):
|
||||
i=30
|
||||
while len(self.message_queue) == 0 and i > 0:
|
||||
self.client.loop()
|
||||
time.sleep(0.5)
|
||||
i -= 1
|
||||
self.assertTrue(i>0, "message receive timed-out")
|
||||
self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received")
|
||||
msg = self.message_queue[0]
|
||||
self.assertEqual(msg.mid,0,"message id not 0")
|
||||
self.assertEqual(msg.topic,"outTopic","message topic incorrect")
|
||||
self.assertEqual(msg.payload,"hello world")
|
||||
self.assertEqual(msg.qos,0,"message qos not 0")
|
||||
self.assertEqual(msg.retain,False,"message retain flag incorrect")
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
import unittest
|
||||
import settings
|
||||
|
||||
import time
|
||||
import mosquitto
|
||||
|
||||
import serial
|
||||
|
||||
def on_message(mosq, obj, msg):
|
||||
obj.message_queue.append(msg)
|
||||
|
||||
class mqtt_publish_in_callback(unittest.TestCase):
|
||||
|
||||
message_queue = []
|
||||
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self)
|
||||
self.client.connect(settings.server_ip)
|
||||
self.client.on_message = on_message
|
||||
self.client.subscribe("outTopic",0)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(self):
|
||||
self.client.disconnect()
|
||||
|
||||
def test_connect(self):
|
||||
i=30
|
||||
while len(self.message_queue) == 0 and i > 0:
|
||||
self.client.loop()
|
||||
time.sleep(0.5)
|
||||
i -= 1
|
||||
self.assertTrue(i>0, "message receive timed-out")
|
||||
self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received")
|
||||
msg = self.message_queue.pop(0)
|
||||
self.assertEqual(msg.mid,0,"message id not 0")
|
||||
self.assertEqual(msg.topic,"outTopic","message topic incorrect")
|
||||
self.assertEqual(msg.payload,"hello world")
|
||||
self.assertEqual(msg.qos,0,"message qos not 0")
|
||||
self.assertEqual(msg.retain,False,"message retain flag incorrect")
|
||||
|
||||
|
||||
def test_publish(self):
|
||||
self.assertEqual(len(self.message_queue), 0, "message queue not empty")
|
||||
payload = "abcdefghij"
|
||||
self.client.publish("inTopic",payload)
|
||||
|
||||
i=30
|
||||
while len(self.message_queue) == 0 and i > 0:
|
||||
self.client.loop()
|
||||
time.sleep(0.5)
|
||||
i -= 1
|
||||
|
||||
self.assertTrue(i>0, "message receive timed-out")
|
||||
self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received")
|
||||
msg = self.message_queue.pop(0)
|
||||
self.assertEqual(msg.mid,0,"message id not 0")
|
||||
self.assertEqual(msg.topic,"outTopic","message topic incorrect")
|
||||
self.assertEqual(msg.payload,payload)
|
||||
self.assertEqual(msg.qos,0,"message qos not 0")
|
||||
self.assertEqual(msg.retain,False,"message retain flag incorrect")
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import shutil
|
||||
from subprocess import call
|
||||
import importlib
|
||||
import unittest
|
||||
import re
|
||||
|
||||
from testcases import settings
|
||||
|
||||
class Workspace(object):
|
||||
|
||||
def __init__(self):
|
||||
self.root_dir = os.getcwd()
|
||||
self.build_dir = os.path.join(self.root_dir,"tmpbin");
|
||||
self.log_dir = os.path.join(self.root_dir,"logs");
|
||||
self.tests_dir = os.path.join(self.root_dir,"testcases");
|
||||
self.examples_dir = os.path.join(self.root_dir,"../PubSubClient/examples")
|
||||
self.examples = []
|
||||
self.tests = []
|
||||
if not os.path.isdir("../PubSubClient"):
|
||||
raise Exception("Cannot find PubSubClient library")
|
||||
try:
|
||||
import ino
|
||||
except:
|
||||
raise Exception("ino tool not installed")
|
||||
|
||||
def init(self):
|
||||
if os.path.isdir(self.build_dir):
|
||||
shutil.rmtree(self.build_dir)
|
||||
os.mkdir(self.build_dir)
|
||||
if os.path.isdir(self.log_dir):
|
||||
shutil.rmtree(self.log_dir)
|
||||
os.mkdir(self.log_dir)
|
||||
|
||||
os.chdir(self.build_dir)
|
||||
call(["ino","init"])
|
||||
|
||||
shutil.copytree("../../PubSubClient","lib/PubSubClient")
|
||||
|
||||
filenames = []
|
||||
for root, dirs, files in os.walk(self.examples_dir):
|
||||
filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")]
|
||||
filenames.sort()
|
||||
for e in filenames:
|
||||
self.examples.append(Sketch(self,e))
|
||||
|
||||
filenames = []
|
||||
for root, dirs, files in os.walk(self.tests_dir):
|
||||
filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")]
|
||||
filenames.sort()
|
||||
for e in filenames:
|
||||
self.tests.append(Sketch(self,e))
|
||||
|
||||
def clean(self):
|
||||
shutil.rmtree(self.build_dir)
|
||||
|
||||
class Sketch(object):
|
||||
def __init__(self,wksp,fn):
|
||||
self.w = wksp
|
||||
self.filename = fn
|
||||
self.basename = os.path.basename(self.filename)
|
||||
self.build_log = os.path.join(self.w.log_dir,"%s.log"%(os.path.basename(self.filename),))
|
||||
self.build_err_log = os.path.join(self.w.log_dir,"%s.err.log"%(os.path.basename(self.filename),))
|
||||
self.build_upload_log = os.path.join(self.w.log_dir,"%s.upload.log"%(os.path.basename(self.filename),))
|
||||
|
||||
def build(self):
|
||||
sys.stdout.write(" Build: ")
|
||||
sys.stdout.flush()
|
||||
|
||||
# Copy sketch over, replacing IP addresses as necessary
|
||||
fin = open(self.filename,"r")
|
||||
lines = fin.readlines()
|
||||
fin.close()
|
||||
fout = open(os.path.join(self.w.build_dir,"src","sketch.ino"),"w")
|
||||
for l in lines:
|
||||
if re.match(r"^byte server\[\] = {",l):
|
||||
fout.write("byte server[] = { %s };\n"%(settings.server_ip.replace(".",", "),))
|
||||
elif re.match(r"^byte ip\[\] = {",l):
|
||||
fout.write("byte ip[] = { %s };\n"%(settings.arduino_ip.replace(".",", "),))
|
||||
else:
|
||||
fout.write(l)
|
||||
fout.flush()
|
||||
fout.close()
|
||||
|
||||
# Run build
|
||||
fout = open(self.build_log, "w")
|
||||
ferr = open(self.build_err_log, "w")
|
||||
rc = call(["ino","build"],stdout=fout,stderr=ferr)
|
||||
fout.close()
|
||||
ferr.close()
|
||||
if rc == 0:
|
||||
sys.stdout.write("pass")
|
||||
sys.stdout.write("\n")
|
||||
return True
|
||||
else:
|
||||
sys.stdout.write("fail")
|
||||
sys.stdout.write("\n")
|
||||
with open(self.build_err_log) as f:
|
||||
for line in f:
|
||||
print " ",line,
|
||||
return False
|
||||
|
||||
def upload(self):
|
||||
sys.stdout.write(" Upload: ")
|
||||
sys.stdout.flush()
|
||||
fout = open(self.build_upload_log, "w")
|
||||
rc = call(["ino","upload"],stdout=fout,stderr=fout)
|
||||
fout.close()
|
||||
if rc == 0:
|
||||
sys.stdout.write("pass")
|
||||
sys.stdout.write("\n")
|
||||
return True
|
||||
else:
|
||||
sys.stdout.write("fail")
|
||||
sys.stdout.write("\n")
|
||||
with open(self.build_upload_log) as f:
|
||||
for line in f:
|
||||
print " ",line,
|
||||
return False
|
||||
|
||||
|
||||
def test(self):
|
||||
# import the matching test case, if it exists
|
||||
try:
|
||||
basename = os.path.basename(self.filename)[:-4]
|
||||
i = importlib.import_module("testcases."+basename)
|
||||
except:
|
||||
sys.stdout.write(" Test: no tests found")
|
||||
sys.stdout.write("\n")
|
||||
return
|
||||
c = getattr(i,basename)
|
||||
|
||||
testmethods = [m for m in dir(c) if m.startswith("test_")]
|
||||
testmethods.sort()
|
||||
tests = []
|
||||
for m in testmethods:
|
||||
tests.append(c(m))
|
||||
|
||||
result = unittest.TestResult()
|
||||
c.setUpClass()
|
||||
if self.upload():
|
||||
sys.stdout.write(" Test: ")
|
||||
sys.stdout.flush()
|
||||
for t in tests:
|
||||
t.run(result)
|
||||
print "%d/%d"%(result.testsRun-len(result.failures)-len(result.errors),result.testsRun)
|
||||
if not result.wasSuccessful():
|
||||
if len(result.failures) > 0:
|
||||
for f in result.failures:
|
||||
print "-- %s"%(str(f[0]),)
|
||||
print f[1]
|
||||
if len(result.errors) > 0:
|
||||
print " Errors:"
|
||||
for f in result.errors:
|
||||
print "-- %s"%(str(f[0]),)
|
||||
print f[1]
|
||||
c.tearDownClass()
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_tests = True
|
||||
|
||||
w = Workspace()
|
||||
w.init()
|
||||
|
||||
for e in w.examples:
|
||||
print "--------------------------------------"
|
||||
print "[%s]"%(e.basename,)
|
||||
if e.build() and run_tests:
|
||||
e.test()
|
||||
for e in w.tests:
|
||||
print "--------------------------------------"
|
||||
print "[%s]"%(e.basename,)
|
||||
if e.build() and run_tests:
|
||||
e.test()
|
||||
|
||||
w.clean()
|
Loading…
Reference in New Issue