diff --git a/.gitignore b/.gitignore index cafa4e3c..077f454b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .pioenvs/ +.pio/ Thumbs.db .DS_Store *.orig diff --git a/.travis.yml b/.travis.yml index 2e8c816a..7a75cc1a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,47 +1,24 @@ sudo: false - -language: bash +language: python os: - linux -before_script: - - "export DISPLAY=:99.0" - - sleep 3 # give xvfb some time to start - - wget http://downloads.arduino.cc/arduino-1.8.5-linux64.tar.xz - - tar xf arduino-1.8.5-linux64.tar.xz - - mv arduino-1.8.5 $HOME/arduino_ide - - cd $HOME/arduino_ide/hardware - - mkdir esp32 - - cd esp32 - - git clone https://github.com/espressif/arduino-esp32.git esp32 - - cd esp32/tools - - python get.py - - cd .. - - mv $TRAVIS_BUILD_DIR/libraries/ESP32SSDP $HOME/arduino_ide/libraries/ - - mv $TRAVIS_BUILD_DIR/libraries/arduinoWebSockets $HOME/arduino_ide/libraries/ - -script: - - cd $TRAVIS_BUILD_DIR - - source command.sh - - export PATH="$HOME/arduino_ide:$PATH" - - arduino --board esp32:esp32:esp32:PartitionScheme=min_spiffs,FlashFreq=40 --pref compiler.warning_level=all --save-prefs - - sed -n '48,72p;73q' $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - sed -i "s/\/\/#define ENABLE_BLUETOOTH/#define ENABLE_BLUETOOTH/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - sed -i "s/#define ENABLE_BLUETOOTH/\/\/#define ENABLE_BLUETOOTH/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - sed -i "s/\/\/#define ENABLE_WIFI/#define ENABLE_WIFI/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - sed -n '48,72p;73q' $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - build_sketch $TRAVIS_BUILD_DIR/Grbl_Esp32/Grbl_Esp32.ino - - sed -i "s/\/\/#define ENABLE_BLUETOOTH/#define ENABLE_BLUETOOTH/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - sed -i "s/#define ENABLE_WIFI/\/\/#define ENABLE_WIFI/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - sed -n '48,72p;73q' $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - build_sketch $TRAVIS_BUILD_DIR/Grbl_Esp32/Grbl_Esp32.ino - - sed -i "s/\/\/#define ENABLE_BLUETOOTH/#define ENABLE_BLUETOOTH/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - sed -i "s/\/\/#define ENABLE_WIFI/#define ENABLE_WIFI/g" $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - sed -n '48,72p;73q' $TRAVIS_BUILD_DIR/Grbl_Esp32/config.h - - build_sketch $TRAVIS_BUILD_DIR/Grbl_Esp32/Grbl_Esp32.ino +cache: + directories: + - "~/.platformio" + +install: + - pip install -U platformio + +script: + - ./configure-features.py -e WIFI -d BLUETOOTH -v + - ./build-machine.py test_drive.h + - ./configure-features.py -e BLUETOOTH -d WIFI -v + - ./build-machine.py test_drive.h + - ./configure-features.py -e BLUETOOTH WIFI -v + - ./build-all.py - notifications: email: on_success: change diff --git a/Grbl_Esp32/Grbl_Esp32.ino b/Grbl_Esp32/Grbl_Esp32.ino index df9e6311..62f3fff6 100644 --- a/Grbl_Esp32/Grbl_Esp32.ino +++ b/Grbl_Esp32/Grbl_Esp32.ino @@ -45,12 +45,13 @@ void setup() { serial_init(); // Setup serial baud rate and interrupts grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Grbl_ESP32 Ver %s Date %s", GRBL_VERSION, GRBL_VERSION_BUILD); // print grbl_esp32 verion info grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Compiled with ESP32 SDK:%s", ESP.getSdkVersion()); // print the SDK version -#ifdef MACHINE_NAME // show the map name at startup -#ifdef MACHINE_EXTRA -#define MACHINE_STRING MACHINE_NAME MACHINE_EXTRA -#else -#define MACHINE_STRING MACHINE_NAME -#endif +// show the map name at startup +#ifdef MACHINE_NAME + #ifdef MACHINE_EXTRA + #define MACHINE_STRING MACHINE_NAME MACHINE_EXTRA + #else + #define MACHINE_STRING MACHINE_NAME + #endif grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Using machine:%s", MACHINE_STRING); #endif settings_init(); // Load Grbl settings from EEPROM diff --git a/Grbl_Esp32/config.h b/Grbl_Esp32/config.h index dbc96f38..0cb8d532 100644 --- a/Grbl_Esp32/config.h +++ b/Grbl_Esp32/config.h @@ -114,7 +114,7 @@ Some features should not be changed. See notes below. //Connect to your local AP with these credentials //#define CONNECT_TO_SSID "your SSID" //#define SSID_PASSWORD "your SSID password" - +//CONFIGURE_EYECATCH_BEGIN (DO NOT MODIFY THIS LINE) #define ENABLE_BLUETOOTH // enable bluetooth #define ENABLE_SD_CARD // enable use of SD Card to run jobs @@ -134,7 +134,7 @@ Some features should not be changed. See notes below. #define ENABLE_CAPTIVE_PORTAL //#define ENABLE_AUTHENTICATION - +//CONFIGURE_EYECATCH_END (DO NOT MODIFY THIS LINE) #define NAMESPACE "GRBL" #define ESP_RADIO_MODE "RADIO_MODE" diff --git a/build-all.py b/build-all.py old mode 100644 new mode 100755 index 502ed8d5..24c646df --- a/build-all.py +++ b/build-all.py @@ -21,9 +21,14 @@ cmd = ['platformio','run'] verbose = '-v' in sys.argv +numErrors = 0 adderBase = '3axis_v4.h' for name in os.listdir('Grbl_Esp32/Machines'): if name.startswith('add_'): - buildMachine(adderBase, addName=name, verbose=verbose) + exitCode = buildMachine(adderBase, addName=name, verbose=verbose) else: - buildMachine(name, verbose=verbose) + exitCode = buildMachine(name, verbose=verbose) + if exitCode != 0: + numErrors += 1 + +sys.exit(numErrors) diff --git a/build-all.sh b/build-all.sh old mode 100644 new mode 100755 index b417aa73..7da6ca0a --- a/build-all.sh +++ b/build-all.sh @@ -4,7 +4,7 @@ # for every machine configuration in the Machines/ directory. # It is useful for automated testing. -trap "echo; exit" SIGINT +trap "echo; exit 255" SIGINT # With -v, show all output. Otherwise, show just the result if [ "$1" = "-v" ]; then @@ -12,18 +12,29 @@ if [ "$1" = "-v" ]; then else FILTER="grep error\|Took" fi +set -o pipefail +NUM_ERRORS=0 + BuildMachine () { basename=$1 addname=$2 - BF="-DMACHINE_FILENAME=$basename" + BF="\"-DMACHINE_FILENAME=$basename\"" displayname=$basename if [ "$addname" != "" ] then - BF="$BF -DMACHINE_FILENAME2=$addname" + BF="$BF \"-DMACHINE_FILENAME2=$addname\"" displayname="$basename + $addname" fi echo "Building machine $displayname" - PLATFORMIO_BUILD_FLAGS=\'$BF\' platformio run 2>&1 | $FILTER + PLATFORMIO_BUILD_FLAGS=$BF platformio run 2>&1 | $FILTER + local re=$? + # check result + if [ $re -ne 0 ]; then + echo "Failed to build machine $displayname" + echo + NUM_ERRORS=$(( NUM_ERRORS + 1 )) + return $re + fi echo } @@ -40,3 +51,5 @@ do adder=`basename $file` BuildMachine $base $adder done + +exit $NUM_ERRORS diff --git a/build-machine.py b/build-machine.py old mode 100644 new mode 100755 index cb668d91..aa821e39 --- a/build-machine.py +++ b/build-machine.py @@ -24,12 +24,15 @@ if '-u' in sys.argv: sys.argv.remove('-u') extraArgs = '--target=upload' +exitCode = 255 if len(sys.argv) == 2: - buildMachine(sys.argv[1], addName=None, verbose=verbose, extraArgs=extraArgs) + exitCode = buildMachine(sys.argv[1], addName=None, verbose=verbose, extraArgs=extraArgs) elif len(sys.argv) == 3: - buildMachine(sys.argv[1], addName=sys.argv[2], verbose=verbose, extraArgs=extraArgs) + exitCode = buildMachine(sys.argv[1], addName=sys.argv[2], verbose=verbose, extraArgs=extraArgs) else: print("Usage: ./build-machine.py [-q] [-u] machine_name.h [add_name.h]") print(' Build for the given machine and optional add-on regardless of machine.h') print(' -q suppresses most messages') print(' -u uploads to the target after compilation') + +sys.exit(exitCode) \ No newline at end of file diff --git a/builder.py b/builder.py old mode 100644 new mode 100755 index d9b09780..ba3bdb6a --- a/builder.py +++ b/builder.py @@ -30,3 +30,4 @@ def buildMachine(baseName, addName=None, verbose=True, extraArgs=None): print(line, end='') app.wait() print() + return app.returncode \ No newline at end of file diff --git a/command.sh b/command.sh old mode 100644 new mode 100755 diff --git a/configure-features.py b/configure-features.py new file mode 100755 index 00000000..7e0ddf1f --- /dev/null +++ b/configure-features.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Grbl_Esp32 configurator +# Copyright (C) 2020 Michiyasu Odaki +# +# This is useful for automated testing, to make sure you haven't broken something +# +# Grbl_Esp32 is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Grbl_Esp32 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Grbl_Esp32. If not, see . + +from __future__ import print_function +import os, sys, argparse, re + +configDirName = r'Grbl_Esp32' +configFileName = r'config.h' + +validFeatureList = [ + 'BLUETOOTH', + 'WIFI', + 'SD_CARD', + 'HTTP', + 'OTA', + 'TELNET', + 'TELNET_WELCOME_MSG', + 'MDNS', + 'SSDP', + 'NOTIFICATIONS', + 'SERIAL2SOCKET_IN', + 'SERIAL2SOCKET_OUT', + 'CAPTIVE_PORTAL', + 'AUTHENTICATION' + ] +eyecatchBeginString = 'CONFIGURE_EYECATCH_BEGIN' +eyecatchEndString = 'CONFIGURE_EYECATCH_END' +enablePrefix = 'ENABLE_' + +def printValidFeatureList(): + print("valid feature names:") + for n in sorted(validFeatureList): + print(" " + n) + +def usage(parser): + parser.print_usage() + printValidFeatureList() + sys.exit(255) + +def parseArgs(defaultConfigPath): + # Argument parser (-h is also available) + parser = argparse.ArgumentParser(description='Configure Grbl_ESP32 features') + parser.add_argument('-v', '--verbose', action='store_true') + parser.add_argument('-c', '--configfile', default=defaultConfigPath) + parser.add_argument('-e', '--enable', nargs='*' + ,help='specify feature name(ex. WIFI)' + #, choices=validFeatureList + ) + parser.add_argument('-d', '--disable', nargs='*' + ,help='specify feature name(ex. BLUETOOTH)' + #,choices=validFeatureList + ) + return parser.parse_args(), parser + +def isValidFeature(feature): + if feature: + if feature.upper() in validFeatureList: + return True #valid + return False #invalid + +def checkFeatureList(optname, features, verbose=False): + if features: + for n in features: + if isValidFeature(n) is True: + #if verbose: + # print("valid " + optname + " feature: " + n) + pass + else: + print("unknown " + optname + " feature: " + n) + return -1 + else: + #if verbose: + # print(optname + " is not specified") + return 0 + + return len(features) + +def resolveConflicts(high_priority, low_priority): + if low_priority: + for n in low_priority[:]: + if n in high_priority: + low_priority.remove(n) + return + +def readConfig(path): + # Read config.h to memory + try: + f = open(path) + except IOError: + print("unable to open file for read: " + path) + sys.exit(255) + else: + try: + src = f.readlines() + except IOError: + print("file read error: " + path) + f.close() + sys.exit(255) + else: + f.close() + return src + +def writeConfig(path, buf): + try: + f = open(path, 'w') + except IOError: + print("unable to open file for write: " + path) + sys.exit(255) + else: + try: + src = f.write(buf) + except IOError: + print("file write error: " + path) + f.close() + sys.exit(255) + else: + f.close() + +def changeConfig(src, enabled, disabled, verbose=False): + dst = "" + regstart = re.compile(r'^\s*//\s*' + eyecatchBeginString) + regend = re.compile(r'^\s*//\s*' + eyecatchEndString) + state = 0; + for line in src: + if state == 0: + # out of the defines block to modify + if regstart.match(line): + state = 1 + dst += line + elif state == 1: + # in the defines block to modify + if regend.match(line): + # end of block found + state = 2 + dst += line + else: + dstLine = "" + if len(enabled) > 0: + for name in enabled: + s = enablePrefix + name + m = re.match(r'^s*//\s*#define\s+(' + s + r'.*)$', line) + if m: + dstLine = "#define " + m.group(1) + '\n' + break + if len(disabled) > 0: + for name in disabled: + s = enablePrefix + name + m = re.match(r'^\s*#define\s+' + s + r'.*$', line) + if m: + dstLine = "//" + line + break + if len(dstLine) != 0: + dst += dstLine + if verbose: + print(dstLine.rstrip()) + else: + dst += line + if verbose: + print(line.rstrip()) + elif state == 2: + dst += line + if state != 2: + print("EYECATCH pair not found. Cancel changes.") + sys.exit(255) + return dst + +def main(): + # Concatinate dir and file + configFilePath = os.path.join(configDirName, configFileName) + + # Parse arguments + args, parser = parseArgs(configFilePath) + + # Set params to local variables + verbose = args.verbose + configFilePath = args.configfile + + # Copy and remove duplicates from enable/disable list + enabledFeatures = [] + disabledFeatures = [] + if args.enable: + enabledFeatures = sorted(set(args.enable), key=args.enable.index) + if args.disable: + disabledFeatures = sorted(set(args.disable), key=args.disable.index) + + # If both enable and disable are specified, treat as enable + # (Remove items from 2nd param if same item in 1st param) + resolveConflicts(enabledFeatures, disabledFeatures) + + # Verification (whether or not to use "choice" with argparse) + numEnables = checkFeatureList("-e", enabledFeatures, verbose) + numDisables = checkFeatureList("-d", disabledFeatures, verbose) + #if verbose: + # print("enables: ", numEnables) + # print(enabledFeatures) + # print("disables: ", numDisables) + # print(disabledFeatures) + # print("config file: " + configFilePath) + + # Final checking about args + if numEnables < 0 or numDisables < 0 or (numEnables == 0 and numDisables == 0): + usage(parser) + + # Check if the target file exists + configFilePathAbs = os.path.abspath(configFilePath) + if verbose: + print("Config path: " + configFilePathAbs) + print() + if not os.path.isfile(configFilePathAbs): + print("config file not found: " + configFilePathAbs) + sys.exit(255) + + # read config file + src = readConfig(configFilePathAbs) + + # Change the specified settings + dst = changeConfig(src, enabledFeatures, disabledFeatures, verbose) + + # Write back + writeConfig(configFilePathAbs, dst) + + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/platformio.ini b/platformio.ini index 8b638982..68fdba59 100644 --- a/platformio.ini +++ b/platformio.ini @@ -21,12 +21,21 @@ lib_deps_builtin = WiFiClientSecure [env:nodemcu-32s] -lib_deps = TMCStepper +lib_deps = + TMCStepper + arduinoWebSockets + ESP32SSPD platform = espressif32 board = nodemcu-32s framework = arduino upload_speed = 512000 board_build.partitions = min_spiffs.csv monitor_speed = 115200 -build_flags = -DCORE_DEBUG_LEVEL=0 -Wno-unused-variable -Wno-unused-function -src_filter = +<*.h> +<*.s> +<*.S> +<*.cpp> +<*.c> +<*.ino> + -<.git/> - - - - +build_flags = + ;-DMACHINE_FILENAME=test_drive.h ;Remove ";" from the beginning of this line and specify the machine file + -DCORE_DEBUG_LEVEL=0 + -Wno-unused-variable + -Wno-unused-function +src_filter = + +<*.h> +<*.s> +<*.S> +<*.cpp> +<*.c> +<*.ino> + + -<.git/> - - - -