fw-server.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #!/usr/bin/env python3
  2. # coding=utf-8
  3. """
  4. fw-server.py - firmware server for Sonoff-Tasmota OTA upgrade
  5. Copyright (C) 2018 Gennaro Tortone
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. Requirements:
  17. - Python3
  18. - pip install netifaces flask
  19. Instructions:
  20. Copy Sonoff-Tasmota firmware binary files in 'fw' directory.
  21. A set of prebuilt files can be downloaded by Sonoff-Tasmota release page:
  22. https://github.com/arendst/Sonoff-Tasmota/releases
  23. Configure your Sonoff-Tasmota device with your fw-server URL:
  24. Firmware Upgrade -> Upgrade by web server
  25. http://<ip_address>:5000/sonoff-minimal.bin
  26. Usage:
  27. ./fw-server.py -d <net_iface> (default: eth0)
  28. or
  29. ./fw-server.py -i <ip_address>
  30. Example:
  31. ./fw-server.py -d wlan0
  32. or
  33. ./fw-server.py -i 192.168.1.10
  34. """
  35. import os.path
  36. from optparse import OptionParser
  37. from sys import exit
  38. from flask import Flask, send_file
  39. import netifaces as ni
  40. usage = "usage: fw-server {-d | -i} arg"
  41. parser = OptionParser(usage)
  42. parser.add_option("-d", "--dev", action="store", type="string",
  43. dest="netdev", default="eth0", help="network interface (default: eth0)")
  44. parser.add_option("-i", "--ip", action="store", type="string",
  45. dest="ip", help="IP address to bind")
  46. (options, args) = parser.parse_args()
  47. netip = None
  48. if options.ip is None:
  49. try:
  50. netip = ni.ifaddresses(options.netdev)[ni.AF_INET][0]['addr']
  51. except Exception as e:
  52. print("E: network interface error - {}".format(e))
  53. exit(1)
  54. else:
  55. netip = options.ip
  56. app = Flask(__name__)
  57. @app.route('/<filename>')
  58. def fw(filename):
  59. if os.path.exists("fw/" + str(filename)):
  60. return send_file("fw/" + str(filename),
  61. attachment_filename=filename,
  62. mimetype='application/octet-stream')
  63. return "ERROR: file not found"
  64. if __name__ == "__main__":
  65. try:
  66. app.run(host=netip)
  67. except Exception as e:
  68. print("E: {}".format(e))