├── .github ├── CONTRIBUTING.md ├── DISCUSSION_TEMPLATE │ ├── Q&A.yml │ └── Questions.yml ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── 1-bug.yml │ ├── 2-feature.md │ └── config.yml └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .isort.cfg ├── .pre-commit-config.yaml ├── ClientInterface.py ├── Diagrams ├── 2008-PreNexusController.jpg ├── Antenna.jpg ├── Battery To USB Power Supply.jpg ├── Cable (End that connecets to Evolution Controller) (2).jpg ├── Cable (End that connecets to Evolution Controller).jpg ├── Cable (full- Liquid cooled models require longer cable).jpg ├── Cable_Connections.jpg ├── Controller_connection(Nexus).jpg ├── Enclosure (1).jpg ├── Enclosure (Antenna on Left-Data on Right).jpg ├── Evolution_Controller.jpg ├── Example_Project.JPG ├── H-100_Controller.png ├── Inside enclosure.jpg ├── MEBAY_RS485 │ ├── Application_WiFi_Uart_Settings1.png │ ├── Application_WiFi_Uart_Settings2.png │ ├── MeBay_Controller_rs485.png │ ├── Mode_selction.png │ ├── STA_Interface_Settings.png │ └── WiFi_Settings_STA_Mode.png ├── Magnets on back of enclosure.jpg ├── Molex_Pinout.png ├── Nexus_Controller.jpg ├── RS485_genmon.jpg ├── Web_UI_Logs.png ├── Web_UI_Maint.png ├── Web_UI_Monitor.png ├── Web_UI_Notifications.png ├── Web_UI_Outage.png ├── Web_UI_Registers.png ├── Web_UI_Settings.png ├── Web_UI_Settings2.png ├── Web_UI_Status.png ├── casestudy │ ├── MLCable.jpeg │ ├── MLPinout.png │ ├── MobileLink2G.jpeg │ ├── PintSizeMeHat.jpeg │ ├── PintSizeMePinout.png │ ├── PowerPactController.jpeg │ ├── Tools.jpeg │ ├── crimppins.jpeg │ ├── pizero-enclosure.jpeg │ ├── repinning-cable.png │ └── tplink-repeater.jpeg ├── enclosure label 2.pdf ├── enclosure label 3.pdf ├── enclosure label.pdf ├── enclosure label.pptx ├── gauge │ ├── gauge01.jpg │ ├── gauge02.jpg │ ├── gauge03.jpg │ ├── gauge04.jpg │ ├── gauge05.jpg │ ├── gauge06.jpg │ └── gauge07.jpg ├── genmon.jpg ├── liquid_cooled_generac_back_of_controller.jpeg ├── powerzoneenable.PNG ├── propane_fuel_gauge.png ├── serial_loopback.jpeg ├── wiring_schematic.jpg └── wiring_schematic.png ├── LICENSE ├── OtherApps ├── ClientInterface.java ├── DIY2TankSensorCalibrate.py ├── check_monitor_system.py ├── kwlog2csv.py ├── modbusdump.py ├── mopeka_utility.py ├── serialconfig.py ├── serialtest.py └── sockettest.py ├── README.md ├── addon ├── genalexa.py ├── gencallmebot.py ├── gencentriconnect.py ├── gencthat.py ├── gencustomgpio.py ├── genemail2sms.py ├── genexercise.py ├── gengpio.py ├── gengpioin.py ├── gengpioledblink.py ├── genlog.py ├── genmopeka.py ├── genmqtt.py ├── genmqttin.py ├── genpushover.py ├── genslack.py ├── gensms.py ├── gensms_modem.py ├── gensms_voip.py ├── gensnmp.py ├── gensyslog.py ├── gentankdiy.py ├── gentankutil.py └── gentemp.py ├── changelog.md ├── conf ├── genalexa.conf ├── gencallmebot.conf ├── gencentriconnect.conf ├── gencthat.conf ├── gencustomgpio.conf ├── genemail2sms.conf ├── genexercise.conf ├── gengpio.conf ├── gengpioin.conf ├── gengpioledblink.conf ├── genloader.conf ├── genmon.conf ├── genmopeka.conf ├── genmqtt.conf ├── genmqttin.conf ├── genpushover.conf ├── genslack.conf ├── gensms.conf ├── gensms_voip.conf ├── gensnmp.conf ├── gentankdiy.conf ├── gentankutil.conf ├── gentemp.conf ├── mymail.conf └── mymodem.conf ├── data ├── ALARMS.txt ├── EvoAC2_Fuel.txt ├── EvoAC_Fuel.txt ├── EvoLC45_Fuel.txt ├── EvoLCParam.txt ├── EvoLC_Fuel.txt ├── NexusLCParam.txt ├── commands │ ├── EvoLC_commands.json │ ├── example_button.json │ └── script │ │ └── example_button.py ├── controller │ ├── Briggs_Stratton_GC-1032.json │ ├── ComAp.json │ ├── Deepsea_controller.json │ ├── Evolution_Liquid_Cooled.json │ ├── Kohler_APM603.json │ ├── MEBAY_DCxx.json │ ├── Power_Zone_410.json │ └── SmartGen_HGM4000.json ├── mib │ ├── Evolution_Liquid_Cooled.json │ ├── README.md │ ├── generac_evo_nexus.json │ ├── genmon.json │ ├── genmon.mib │ ├── h_100.json │ └── powerzone.json └── tooltips.txt ├── feature_requests.md ├── genloader.py ├── genmon.py ├── genmonlib ├── __init__.py ├── controller.py ├── custom_controller.py ├── gaugediy.py ├── generac_HPanel.py ├── generac_evolution.py ├── generac_powerzone.py ├── modbus_evo2.py ├── modbus_file.py ├── modbusbase.py ├── mycentriconnect.py ├── myclient.py ├── mycommon.py ├── myconfig.py ├── mycrypto.py ├── mylog.py ├── mymail.py ├── mymodbus.py ├── mymodem.py ├── mymopeka.py ├── mymsgqueue.py ├── mynotify.py ├── mypipe.py ├── myplatform.py ├── myserial.py ├── myserialtcp.py ├── mysupport.py ├── mytankutility.py ├── mythread.py ├── mytile.py ├── myvoipms.py ├── myweather.py └── program_defaults.py ├── genmonmaint.sh ├── genserv.py ├── requirements.txt ├── startgenmon.sh ├── static ├── closure-compiler.py ├── css │ ├── jquery-ui.css │ ├── jquery.CalendarHeatmap.css │ ├── jquery.idealforms.css │ ├── jquery.jqplot.min.css │ ├── jquery.timepicker.min.css │ ├── lc_switch.css │ ├── print.css │ ├── selectize.default.css │ ├── tooltipster.bundle.min.css │ ├── vex-theme-os.css │ └── vex.css ├── favicon.ico ├── genmon.css ├── genmon.js ├── images │ ├── GenmonLogo.png │ ├── addons.png │ ├── raw │ │ ├── Genmon.png │ │ ├── Genmon_small.png │ │ ├── about.png │ │ ├── addon.png │ │ ├── alert_large.png │ │ ├── alert_small.png │ │ ├── dd_arrow.gif │ │ ├── fuel.png │ │ ├── journal.png │ │ ├── log.png │ │ ├── maintenance.png │ │ ├── monitor.png │ │ ├── notifications.png │ │ ├── outage.png │ │ ├── print10.png │ │ ├── print24.png │ │ ├── print60.png │ │ ├── registers.png │ │ ├── remove_bin.png │ │ ├── selftest.png │ │ ├── selftest_small.png │ │ ├── settings.png │ │ ├── status.png │ │ ├── temp1.png │ │ ├── temp2.png │ │ ├── temp3.png │ │ ├── temp4.png │ │ ├── title-bg.gif │ │ ├── validation.png │ │ ├── validation_ok.png │ │ ├── validation_text.png │ │ ├── wifi1.png │ │ ├── wifi2.png │ │ ├── wifi3.png │ │ └── wifi4.png │ ├── sprites.png │ ├── transparent.png │ ├── ui-bg_flat_75_ffffff_40x100.png │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ ├── ui-bg_glass_65_ffffff_1x400.png │ ├── ui-bg_glass_75_dadada_1x400.png │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ ├── ui-icons_222222_256x240.png │ └── ui-icons_454545_256x240.png ├── index.html ├── index_lowbandwith.html ├── index_verbose.html ├── internal.css ├── internal.html ├── internal.js ├── js │ ├── gauge.min.js │ ├── jqplot.dateAxisRenderer.js │ ├── jquery-3.7.0.min.js │ ├── jquery-ui.min.js │ ├── jquery.CalendarHeatmap.genmon.js │ ├── jquery.idealforms.genmon.js │ ├── jquery.jqplot.min.js │ ├── jquery.qrcode.min.js │ ├── jquery.timepicker.min.js │ ├── jquery.ui.touch-punch.min.js │ ├── keep.silk.alive.js │ ├── lc_switch.genmon.js │ ├── moment.min.js │ ├── packery.pkgd.min.js │ ├── printThis.js │ ├── selectize.min.js │ ├── tooltipster.bundle.js │ ├── tooltipster.bundle.min.js │ └── vex.combined.min.js ├── libraries.min.css ├── libraries.min.js └── media │ └── media.mp3 └── templates ├── command_template.html ├── locked.html ├── login.html └── mfa.html /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | You feedback and questions are welcome and they help improve the documentation and software. The following are way we can maximize the feedback response. 2 | 3 | 1) Review open and closed threads to see if your question has been asked before 4 | 2) Please post new questions to a new thread 5 | 3) Include your generator model along with what controller you are using (e.g. Generac 6730 with Evolution Controller, Air Cooled) 6 | 4) Please include a photo if applicable (i.e. photos work great for enclosure and cable questions) or copy and past output of programs if applicable. 7 | 5) Please run [pre-commit](https://pre-commit.com/) on any code before committing. 8 | -------------------------------------------------------------------------------- /.github/DISCUSSION_TEMPLATE/Q&A.yml: -------------------------------------------------------------------------------- 1 | body: 2 | - type: textarea 3 | attributes: 4 | label: Question to be asked (include generator make and model) 5 | placeholder: Detailed question 6 | validations: 7 | required: true 8 | - type: textarea 9 | attributes: 10 | label: Version 11 | placeholder: Genmon Version 12 | validations: 13 | required: true 14 | -------------------------------------------------------------------------------- /.github/DISCUSSION_TEMPLATE/Questions.yml: -------------------------------------------------------------------------------- 1 | labels: [question] 2 | body: 3 | - type: markdown 4 | attributes: 5 | value: | 6 | Thanks for taking the time to fill out this form. 7 | 8 | - type: checkboxes 9 | id: checklist 10 | attributes: 11 | label: "Checklist" 12 | options: 13 | - label: "I made sure that there are *no existing issues or discussions* - [open issues](https://github.com/jgyates/genmon/issues),[closed issues](https://github.com/jgyates/genmon/issues?q=is%3Aissue+is%3Aclosed),[open discussion](https://github.com/jgyates/genmon/discussions), [closed discussion](https://github.com/jgyates/genmon/discussions/categories/questions?discussions_q=is%3Aclosed) - which may answer my question or that I could contribute my information to." 14 | required: true 15 | - label: "I have read the [Known Issues Wiki Page](https://github.com/jgyates/genmon/wiki/Appendix-D-Known-Issues) and my question / issue is not listed." 16 | required: true 17 | - label: "I have provided the version of the software and the operating system in my post." 18 | required: true 19 | - label: "If I have an issue with genmon not communicating with the controller, I have read and followed the [serial troubleshooting guide](https://github.com/jgyates/genmon/wiki/3.6---Serial-Troubleshooting)." 20 | required: true 21 | - label: "I have included the generator make and model in my submission." 22 | required: true 23 | 24 | - type: textarea 25 | attributes: 26 | label: Version 27 | placeholder: Genmon Version 28 | 29 | - type: dropdown 30 | id: logssubmitted 31 | attributes: 32 | label: Have you submitted your log files from the About page? Note that outbound email must be working for logs to be submitted. 33 | options: 34 | - I have submitted logs 35 | - I have not submitted logs 36 | validations: 37 | required: true 38 | 39 | - type: textarea 40 | id: what-is-the-question 41 | attributes: 42 | label: What is/are your question(s)? 43 | validations: 44 | required: true 45 | 46 | - type: textarea 47 | id: additional-information 48 | attributes: 49 | label: Additional information 50 | description: Any other information you'd like to include, for instance pictures, screen captures, etc. -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: jgyates 4 | custom: ["https://www.paypal.me/jgyates", "www.venmo.com/u/j-g-yates"] 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | **Creating and new issue is for reporting bugs or problems with the software. All other questions, feature requests, informational posts, etc should be posted in the project Discussion section here: https://github.com/jgyates/genmon/discussions.** 3 | 4 | Use the template below if you want to report a bug. If you have a question or a feature request you can ignore the questions below. This is a template so feel free to remove any of this text. Try to include the info below when applicable. 5 | 6 | ***NOTE:*** If you are having issues with your serial connection, please read this page before posting: 7 | 8 | https://github.com/jgyates/genmon/wiki/3.6---Serial-Troubleshooting 9 | 10 | If you are having other issues, please see the following page: 11 | 12 | https://github.com/jgyates/genmon/wiki/3.5---General-Troubleshooting 13 | 14 | You can search past issues by removing the "is:open" keywords from the search window and adding any keywords that are relevant to your issue. 15 | 16 | If you need to send you logs and registers to the developer, if your email is setup and working properly you can click send your logs on the About page in the web interface. 17 | 18 | ### Expected Behavior 19 | 20 | {Please write here} 21 | 22 | ### Actual Behavior 23 | 24 | {Please write here} 25 | 26 | ### Steps to Reproduce (including precondition) 27 | 28 | {Please write here} 29 | 30 | ### Screenshot or Pictures relating to the problem (if possible) 31 | 32 | {Please write here} 33 | 34 | ### Your Environment 35 | 36 | - Generator Model: {Please write here} 37 | - Genmon Logs: Submit via the About page 38 | - Genmon Version: {Please write here} 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-bug.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Report something not working correctly. 3 | body: 4 | - type: textarea 5 | id: repro 6 | attributes: 7 | label: Steps to Reproduce 8 | description: How can we reproduce? Screen captures can help. 9 | placeholder: |- 10 | 1. foo 11 | 2. bar 12 | 3. baz 13 | validations: 14 | required: true 15 | - type: textarea 16 | id: expected 17 | attributes: 18 | label: Expected Result 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: actual 23 | attributes: 24 | label: Actual Result 25 | description: Logs? Screenshots? Yes, please. 26 | validations: 27 | required: true 28 | - type: textarea 29 | id: version-info 30 | attributes: 31 | label: Version Info 32 | description: Genmon Version` 33 | validations: 34 | required: true 35 | - type: textarea 36 | id: logs 37 | attributes: 38 | label: Logs 39 | description: Logs submitted from the About page or attached to this thread from /var/log/. 40 | validations: 41 | required: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Suggestion 3 | about: Want to report a suggestion for a feature? 4 | --- -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Discussions 4 | url: https://github.com/jgyates/genmon/discussions 5 | about: Please ask and answer questions here. -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Pull Request Template 2 | 3 | ## Description 4 | 5 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 6 | 7 | Fixes # (issue) 8 | 9 | ## Type of change 10 | 11 | Please delete options that are not relevant. 12 | 13 | - [ ] Bug fix (non-breaking change which fixes an issue) 14 | - [ ] New feature (non-breaking change which adds functionality) 15 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 16 | - [ ] This change requires a documentation update 17 | 18 | ## How Has This Been Tested? 19 | 20 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 21 | 22 | - [ ] Test A 23 | - [ ] Test B 24 | 25 | **Test Configuration**: 26 | * Firmware version: 27 | * Hardware: 28 | 29 | ## Checklist: 30 | 31 | - [ ] Are any new libraries required and have they been added to the install scripts 32 | - [ ] My code follows the existing code style and formatting of this project 33 | - [ ] I have performed a self-review of my own code 34 | - [ ] I have reasonably commented my code, particularly in hard-to-understand areas 35 | - [ ] I have made corresponding changes to the documentation 36 | - [ ] My changes generate no new warnings or errors 37 | - [ ] I have checked my code and corrected any misspellings 38 | - [ ] I have tested any python code on 3.x 39 | - [ ] I have tested any javascript on most popular browsers for compatibility 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | outage.txt 2 | kwlog.txt 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *,cover 49 | .hypothesis/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # IPython Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # dotenv 82 | .env 83 | 84 | # virtualenv 85 | venv/ 86 | ENV/ 87 | 88 | # Spyder project settings 89 | .spyderproject 90 | 91 | # Rope project settings 92 | .ropeproject 93 | 94 | # OS generated files # 95 | ###################### 96 | .DS_Store 97 | .DS_Store? 98 | ._* 99 | .Spotlight-V100 100 | .Trashes 101 | ehthumbs.db 102 | Thumbs.db 103 | /.vs 104 | -------------------------------------------------------------------------------- /.isort.cfg: -------------------------------------------------------------------------------- 1 | [settings] 2 | profile = black 3 | multi_line_output = 3 4 | sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER 5 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.3.0 4 | hooks: 5 | - id: trailing-whitespace 6 | - id: end-of-file-fixer 7 | exclude: \.(min\.css|min\.js|po|mo)$ 8 | - repo: https://github.com/psf/black 9 | rev: 22.10.0 10 | hooks: 11 | - id: black 12 | language_version: python3.8 13 | - repo: https://github.com/pre-commit/mirrors-isort 14 | rev: "v5.10.1" 15 | hooks: 16 | - id: isort 17 | # - repo: https://gitlab.com/pycqa/flake8 18 | # rev: "3.9.2" 19 | # hooks: 20 | # - id: flake8 21 | -------------------------------------------------------------------------------- /ClientInterface.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------------------------- 3 | # FILE: ClientInterface.py 4 | # PURPOSE: 5 | # 6 | # AUTHOR: Jason G Yates 7 | # DATE: 17-Dec-2016 8 | # MODIFICATIONS: 9 | # ------------------------------------------------------------------------------- 10 | import getopt 11 | import signal 12 | import sys 13 | 14 | try: 15 | from genmonlib.myclient import ClientInterface 16 | from genmonlib.mylog import SetupLogger 17 | from genmonlib.program_defaults import ProgramDefaults 18 | except Exception as e1: 19 | print( 20 | "\n\nThis program requires the modules located in the genmonlib directory in the github repository.\n" 21 | ) 22 | print( 23 | "Please see the project documentation at https://github.com/jgyates/genmon.\n" 24 | ) 25 | print("Error: " + str(e1)) 26 | sys.exit(2) 27 | 28 | # ---------- Signal Handler ---------------------------------------------------- 29 | def signal_handler(signal, frame): 30 | 31 | if MyClientInterface != None: 32 | MyClientInterface.Close() 33 | sys.exit(0) 34 | 35 | 36 | # ------------------- Command-line interface for monitor ------------------------ 37 | if __name__ == "__main__": # usage program.py [server_address] [port] 38 | address = ProgramDefaults.LocalHost 39 | port = ProgramDefaults.ServerPort 40 | 41 | # log errors in this module to a file 42 | console = SetupLogger("client_console", log_file="", stream=True) 43 | HelpStr = "\npython ClientInterface.py -a -p \n" 44 | try: 45 | opts, args = getopt.getopt(sys.argv[1:], "hp:a:", ["help", "port=", "address="]) 46 | except getopt.GetoptError: 47 | console.error("Invalid command line argument.") 48 | sys.exit(2) 49 | 50 | MyClientInterface = None 51 | try: 52 | for opt, arg in opts: 53 | if opt == "-h": 54 | console.error(HelpStr) 55 | sys.exit() 56 | elif opt in ("-a", "--address"): 57 | address = arg 58 | elif opt in ("-p", "--port"): 59 | port = int(arg) 60 | except Exception as e1: 61 | console.error("Error parsing: " + str(e1)) 62 | sys.exit(2) 63 | 64 | log = SetupLogger("client", "client.log") 65 | 66 | # Set the signal handler 67 | signal.signal(signal.SIGINT, signal_handler) 68 | signal.signal(signal.SIGTERM, signal_handler) 69 | 70 | MyClientInterface = ClientInterface(host=address, port=port, log=log) 71 | 72 | try: 73 | 74 | while True: 75 | if sys.version_info[0] < 3: # Python 2.x 76 | line = raw_input(">") 77 | else: # python 3.x 78 | line = input(">") 79 | 80 | if line.lower() == "exit": 81 | break 82 | if len(line): 83 | data = MyClientInterface.ProcessMonitorCommand(line) 84 | print(data) 85 | 86 | except Exception as e1: 87 | console.error("Error: " + str(e1)) 88 | MyClientInterface.Close() 89 | -------------------------------------------------------------------------------- /Diagrams/2008-PreNexusController.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/2008-PreNexusController.jpg -------------------------------------------------------------------------------- /Diagrams/Antenna.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Antenna.jpg -------------------------------------------------------------------------------- /Diagrams/Battery To USB Power Supply.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Battery To USB Power Supply.jpg -------------------------------------------------------------------------------- /Diagrams/Cable (End that connecets to Evolution Controller) (2).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Cable (End that connecets to Evolution Controller) (2).jpg -------------------------------------------------------------------------------- /Diagrams/Cable (End that connecets to Evolution Controller).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Cable (End that connecets to Evolution Controller).jpg -------------------------------------------------------------------------------- /Diagrams/Cable (full- Liquid cooled models require longer cable).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Cable (full- Liquid cooled models require longer cable).jpg -------------------------------------------------------------------------------- /Diagrams/Cable_Connections.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Cable_Connections.jpg -------------------------------------------------------------------------------- /Diagrams/Controller_connection(Nexus).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Controller_connection(Nexus).jpg -------------------------------------------------------------------------------- /Diagrams/Enclosure (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Enclosure (1).jpg -------------------------------------------------------------------------------- /Diagrams/Enclosure (Antenna on Left-Data on Right).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Enclosure (Antenna on Left-Data on Right).jpg -------------------------------------------------------------------------------- /Diagrams/Evolution_Controller.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Evolution_Controller.jpg -------------------------------------------------------------------------------- /Diagrams/Example_Project.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Example_Project.JPG -------------------------------------------------------------------------------- /Diagrams/H-100_Controller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/H-100_Controller.png -------------------------------------------------------------------------------- /Diagrams/Inside enclosure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Inside enclosure.jpg -------------------------------------------------------------------------------- /Diagrams/MEBAY_RS485/Application_WiFi_Uart_Settings1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/MEBAY_RS485/Application_WiFi_Uart_Settings1.png -------------------------------------------------------------------------------- /Diagrams/MEBAY_RS485/Application_WiFi_Uart_Settings2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/MEBAY_RS485/Application_WiFi_Uart_Settings2.png -------------------------------------------------------------------------------- /Diagrams/MEBAY_RS485/MeBay_Controller_rs485.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/MEBAY_RS485/MeBay_Controller_rs485.png -------------------------------------------------------------------------------- /Diagrams/MEBAY_RS485/Mode_selction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/MEBAY_RS485/Mode_selction.png -------------------------------------------------------------------------------- /Diagrams/MEBAY_RS485/STA_Interface_Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/MEBAY_RS485/STA_Interface_Settings.png -------------------------------------------------------------------------------- /Diagrams/MEBAY_RS485/WiFi_Settings_STA_Mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/MEBAY_RS485/WiFi_Settings_STA_Mode.png -------------------------------------------------------------------------------- /Diagrams/Magnets on back of enclosure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Magnets on back of enclosure.jpg -------------------------------------------------------------------------------- /Diagrams/Molex_Pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Molex_Pinout.png -------------------------------------------------------------------------------- /Diagrams/Nexus_Controller.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Nexus_Controller.jpg -------------------------------------------------------------------------------- /Diagrams/RS485_genmon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/RS485_genmon.jpg -------------------------------------------------------------------------------- /Diagrams/Web_UI_Logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Web_UI_Logs.png -------------------------------------------------------------------------------- /Diagrams/Web_UI_Maint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Web_UI_Maint.png -------------------------------------------------------------------------------- /Diagrams/Web_UI_Monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Web_UI_Monitor.png -------------------------------------------------------------------------------- /Diagrams/Web_UI_Notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Web_UI_Notifications.png -------------------------------------------------------------------------------- /Diagrams/Web_UI_Outage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Web_UI_Outage.png -------------------------------------------------------------------------------- /Diagrams/Web_UI_Registers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Web_UI_Registers.png -------------------------------------------------------------------------------- /Diagrams/Web_UI_Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Web_UI_Settings.png -------------------------------------------------------------------------------- /Diagrams/Web_UI_Settings2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Web_UI_Settings2.png -------------------------------------------------------------------------------- /Diagrams/Web_UI_Status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/Web_UI_Status.png -------------------------------------------------------------------------------- /Diagrams/casestudy/MLCable.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/MLCable.jpeg -------------------------------------------------------------------------------- /Diagrams/casestudy/MLPinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/MLPinout.png -------------------------------------------------------------------------------- /Diagrams/casestudy/MobileLink2G.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/MobileLink2G.jpeg -------------------------------------------------------------------------------- /Diagrams/casestudy/PintSizeMeHat.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/PintSizeMeHat.jpeg -------------------------------------------------------------------------------- /Diagrams/casestudy/PintSizeMePinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/PintSizeMePinout.png -------------------------------------------------------------------------------- /Diagrams/casestudy/PowerPactController.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/PowerPactController.jpeg -------------------------------------------------------------------------------- /Diagrams/casestudy/Tools.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/Tools.jpeg -------------------------------------------------------------------------------- /Diagrams/casestudy/crimppins.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/crimppins.jpeg -------------------------------------------------------------------------------- /Diagrams/casestudy/pizero-enclosure.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/pizero-enclosure.jpeg -------------------------------------------------------------------------------- /Diagrams/casestudy/repinning-cable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/repinning-cable.png -------------------------------------------------------------------------------- /Diagrams/casestudy/tplink-repeater.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/casestudy/tplink-repeater.jpeg -------------------------------------------------------------------------------- /Diagrams/enclosure label 2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/enclosure label 2.pdf -------------------------------------------------------------------------------- /Diagrams/enclosure label 3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/enclosure label 3.pdf -------------------------------------------------------------------------------- /Diagrams/enclosure label.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/enclosure label.pdf -------------------------------------------------------------------------------- /Diagrams/enclosure label.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/enclosure label.pptx -------------------------------------------------------------------------------- /Diagrams/gauge/gauge01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/gauge/gauge01.jpg -------------------------------------------------------------------------------- /Diagrams/gauge/gauge02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/gauge/gauge02.jpg -------------------------------------------------------------------------------- /Diagrams/gauge/gauge03.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/gauge/gauge03.jpg -------------------------------------------------------------------------------- /Diagrams/gauge/gauge04.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/gauge/gauge04.jpg -------------------------------------------------------------------------------- /Diagrams/gauge/gauge05.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/gauge/gauge05.jpg -------------------------------------------------------------------------------- /Diagrams/gauge/gauge06.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/gauge/gauge06.jpg -------------------------------------------------------------------------------- /Diagrams/gauge/gauge07.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/gauge/gauge07.jpg -------------------------------------------------------------------------------- /Diagrams/genmon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/genmon.jpg -------------------------------------------------------------------------------- /Diagrams/liquid_cooled_generac_back_of_controller.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/liquid_cooled_generac_back_of_controller.jpeg -------------------------------------------------------------------------------- /Diagrams/powerzoneenable.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/powerzoneenable.PNG -------------------------------------------------------------------------------- /Diagrams/propane_fuel_gauge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/propane_fuel_gauge.png -------------------------------------------------------------------------------- /Diagrams/serial_loopback.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/serial_loopback.jpeg -------------------------------------------------------------------------------- /Diagrams/wiring_schematic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/wiring_schematic.jpg -------------------------------------------------------------------------------- /Diagrams/wiring_schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/Diagrams/wiring_schematic.png -------------------------------------------------------------------------------- /OtherApps/check_monitor_system.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------ 3 | # FILE: check_monitor_system.py 4 | # PURPOSE: Nagios plugin for checking monitor system 5 | # ------------------------------------------------------------ 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | import getopt 21 | import socket 22 | import sys 23 | 24 | 25 | def main(argv): 26 | myhostaddress = "" 27 | 28 | try: 29 | opts, args = getopt.getopt(argv, "H:h") 30 | except getopt.GetoptError: 31 | print("USAGE: check_monitor_system.py -H ") 32 | sys.exit(2) 33 | 34 | for opt, arg in opts: 35 | if opt == "-h": 36 | print("USAGE: check_monitor_system.py -H ") 37 | sys.exit(1) 38 | elif opt in ("-H"): 39 | myhostaddress = arg 40 | 41 | if myhostaddress == "": 42 | print("USAGE: check_monitor_system.py -H ") 43 | sys.exit(1) 44 | 45 | try: 46 | # create an INET, STREAMing socket 47 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 48 | # now connect to the server on our port 49 | s.connect((myhostaddress, 9082)) 50 | s.settimeout(8.0) # blok on recv 51 | except: 52 | print("CRITICAL: Monitor Program not running") 53 | sys.exit(2) 54 | 55 | try: 56 | # read serial data from socket 57 | data = s.recv(1024) 58 | s.shutdown(socket.SHUT_RDWR) 59 | s.close() 60 | data = data.decode("ascii") 61 | except: 62 | # if not receiving then check exit 63 | print("CRITICAL: No Data") 64 | sys.exit(2) 65 | 66 | # print data 67 | if "OK" in data: # 68 | print(data) 69 | sys.exit(0) 70 | elif "CRITICAL" in data: 71 | print(data) 72 | sys.exit(2) 73 | elif "WARNING" in data: 74 | print(data) 75 | sys.exit(1) 76 | else: 77 | print(data) 78 | sys.exit(1) 79 | 80 | 81 | if __name__ == "__main__": 82 | main(sys.argv[1:]) 83 | -------------------------------------------------------------------------------- /OtherApps/kwlog2csv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------------------------- 3 | # FILE: kwlog2csv.py 4 | # PURPOSE: kwlog2csv.py support program to allow testing of generator 5 | # run time 6 | # 7 | # AUTHOR: Jason G Yates 8 | # DATE: 17-Mar-2018 9 | # 10 | # MODIFICATIONS: 11 | # ------------------------------------------------------------------------------- 12 | 13 | 14 | import getopt 15 | import json 16 | import sys 17 | 18 | sys.path.append("..") # Adds higher directory to python modules path. 19 | 20 | try: 21 | from genmonlib.myclient import ClientInterface 22 | from genmonlib.mylog import SetupLogger 23 | from genmonlib.program_defaults import ProgramDefaults 24 | except: 25 | print( 26 | "\n\nThis program requires the modules located in the genmonlib directory in the github repository.\n" 27 | ) 28 | print( 29 | "Please see the project documentation at https://github.com/jgyates/genmon.\n" 30 | ) 31 | sys.exit(2) 32 | 33 | 34 | # ------------ GeneratorDevice::LogToFile---------------------------------------- 35 | def LogToFile(File, TimeDate, Value): 36 | 37 | if not len(File): 38 | print("Error in LogToFile: invalid filename") 39 | 40 | try: 41 | with open(File, "a") as LogFile: # opens file 42 | LogFile.write(TimeDate + "," + Value + "\n") 43 | LogFile.flush() 44 | except Exception as e1: 45 | print("Error in LogToFile : File: %s: %s " % (File, str(e1))) 46 | 47 | 48 | # ------------------- Command-line interface for program ------------------------ 49 | if __name__ == "__main__": 50 | 51 | address = ProgramDefaults.LocalHost 52 | port = ProgramDefaults.ServerPort 53 | fileName = "" 54 | 55 | HelpStr = "\npython3 kwlog2csv.py -a -f \n" 56 | HelpStr += "\n Example: python kwlog2csv.py -a 192.168.1.100 -f Output.csv \n" 57 | HelpStr += "\n" 58 | HelpStr += "\n -a Address of system with genmon (omit for localhost)" 59 | HelpStr += "\n -f Filename to output the kW log in CSV format" 60 | HelpStr += "\n \n" 61 | 62 | try: 63 | opts, args = getopt.getopt( 64 | sys.argv[1:], "ha:f:p:", ["address=", "filename=", "port="] 65 | ) 66 | except getopt.GetoptError: 67 | print(HelpStr) 68 | sys.exit(2) 69 | 70 | try: 71 | for opt, arg in opts: 72 | if opt == "-h": 73 | print(HelpStr) 74 | sys.exit() 75 | elif opt in ("-a", "--address"): 76 | address = arg 77 | print("Address is : %s" % address) 78 | elif opt in ("-p", "--port"): 79 | port = int(arg) 80 | print("Port is : %s" % address) 81 | elif opt in ("-f", "--filename"): 82 | fileName = arg 83 | print("Output file is : %s" % fileName) 84 | except Exception as e1: 85 | print("Error : " + str(e1)) 86 | sys.exit(2) 87 | 88 | if not len(address): 89 | print("Address is : localhost") 90 | address = ProgramDefaults.LocalHost 91 | 92 | if not len(fileName): 93 | print(HelpStr) 94 | sys.exit(2) 95 | 96 | try: 97 | log = SetupLogger("client", "kwlog2csv.log") 98 | 99 | MyClientInterface = ClientInterface(host=address, port=port, log=log) 100 | 101 | data = MyClientInterface.ProcessMonitorCommand("generator: power_log_json") 102 | 103 | data = json.loads(data) 104 | 105 | for Time, Value in reversed(data): 106 | LogToFile(fileName, Time, Value) 107 | 108 | except Exception as e1: 109 | print("Error (1): " + str(e1)) 110 | -------------------------------------------------------------------------------- /OtherApps/mopeka_utility.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------- 2 | # FILE: mopekautility.py 3 | # PURPOSE: app for mopeka pro sensor support 4 | # 5 | # AUTHOR: Jason G Yates 6 | # DATE: 2-Aug-2022 7 | # 8 | # MODIFICATIONS: 9 | # ------------------------------------------------------------------------------- 10 | 11 | import os 12 | import signal 13 | import sys 14 | import time 15 | from subprocess import PIPE, Popen 16 | 17 | # Adds higher directory to python modules path. 18 | sys.path.append(os.path.dirname(sys.path[0])) 19 | 20 | try: 21 | import bleson 22 | from genmonlib.mymopeka import MopekaBT, ScanningMode 23 | except Exception as e1: 24 | print("\n\nThis program is used to support using the Mopeka BT sensor with genmon.") 25 | 26 | managedfile = "/usr/lib/python" + str(sys.version_info.major) + "." + str(sys.version_info.minor) + "/EXTERNALLY-MANAGED" 27 | if os.path.isfile(managedfile): 28 | print("\n\nYou appear to be running in a managed python environemnt. To run this program see this page: ") 29 | print("\n\n https://github.com/jgyates/genmon/wiki/Appendix-S---Working-in-a-Managed-Python-Environment\n") 30 | else: 31 | print("\nThe required python libraries are not installed. You must run the setup script first.\n") 32 | print("\n\n https://github.com/jgyates/genmon/wiki/3.3--Setup-genmon-software") 33 | 34 | print("\n\nError: " + str(e1)) 35 | sys.exit(2) 36 | 37 | 38 | # ----------SignalClose-------------------------------------------------------- 39 | def SignalClose(signum, frame): 40 | 41 | sys.exit(1) 42 | 43 | 44 | # ------------------------------------------------------------------------------- 45 | def CheckServiceOutput(Output): 46 | 47 | try: 48 | for line in iter(Output.splitlines()): 49 | if sys.version_info[0] >= 3: 50 | line = line.decode() 51 | if "Loaded:" in line: 52 | line = line.strip() 53 | lineitems = line.split(";") 54 | if len(lineitems) >= 2 and "disabled" in lineitems[1].lower(): 55 | return True 56 | else: 57 | return False 58 | return False 59 | except Exception as e1: 60 | print("Program Error: (CheckServiceOutput): " + str(e1) + " " + GetErrorInfo()) 61 | sys.exit(2) 62 | 63 | 64 | # ------------------------------------------------------------------------------- 65 | def ServiceIsEnabled(servicename): 66 | try: 67 | process = Popen(["systemctl", "status", servicename], stdout=PIPE) 68 | output, _error = process.communicate() 69 | rc = process.returncode 70 | return not CheckServiceOutput(output) 71 | 72 | except Exception as e1: 73 | print("Program Error (ServiceIsEnabled): " + str(e1) + " " + GetErrorInfo()) 74 | sys.exit(2) 75 | 76 | 77 | # ------------------GetErrorInfo------------------------------------------------- 78 | def GetErrorInfo(): 79 | exc_type, exc_obj, exc_tb = sys.exc_info() 80 | fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] 81 | lineno = exc_tb.tb_lineno 82 | return fname + ":" + str(lineno) 83 | 84 | 85 | # ------------------main--------------------------------------------------------- 86 | if __name__ == "__main__": 87 | 88 | if os.geteuid() != 0: 89 | print( 90 | "You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting." 91 | ) 92 | sys.exit(2) 93 | 94 | try: 95 | 96 | signal.signal(signal.SIGTERM, SignalClose) 97 | signal.signal(signal.SIGINT, SignalClose) 98 | 99 | service = MopekaBT(mode = ScanningMode.DISCOVERY) 100 | 101 | print("\nNOTE: This program will look for Mopeka Pro Sensors. The SYNC button must be pressed and held for the discovery process to work.\n") 102 | print("Starting Discovery....") 103 | 104 | try: 105 | service.Start() 106 | except Exception as e1: 107 | print("Error starting discovery. Validate that Blootooth is enabled: " + str(e1) + " " + GetErrorInfo()) 108 | print("\n") 109 | sys.exit(2) 110 | 111 | time.sleep(5) 112 | service.Stop() 113 | 114 | print("Discovery Stats: \n") 115 | print("\tProcessed Advertisments: " + str(service.processed_advertisments)) 116 | print("\tIgnored Advertisments: " + str(service.ignored_advertisments)) 117 | print("\tZero Length Advertisments: " + str(service.zero_lenght_advertisments)) 118 | print(f"\nFinished Discovery. Found {len(service.discovered_sensors)} new sensor(s):\n") 119 | 120 | for sensor in service.discovered_sensors.values(): 121 | print("Sensor Address: " + str(sensor.address)) 122 | print("Battery Percentage: " + str(sensor.last_reading.BatteryPercent) + "%%") 123 | print("Sensor Temperature: " + str(sensor.last_reading.TemperatureInCelsius) + " C") 124 | print("Tank Level Reading: " + str(sensor.last_reading.TankLevelInMM) + "mm") 125 | print("\n") 126 | 127 | if len(service.discovered_sensors): 128 | print("Use the sensor address above as the tank address parameter in the genmon add on settings.\n") 129 | 130 | except Exception as e1: 131 | print("Program Error (main): " + str(e1) + " " + GetErrorInfo()) 132 | print("\n") 133 | sys.exit(2) 134 | -------------------------------------------------------------------------------- /OtherApps/sockettest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------ 3 | # FILE: serialtest.py 4 | # PURPOSE: 5 | # 6 | # AUTHOR: Jason G Yates 7 | # DATE: 12-Apr-2017 8 | # Free software. Use at your own risk. 9 | # MODIFICATIONS: 10 | # ------------------------------------------------------------ 11 | 12 | 13 | import getopt 14 | import socket 15 | import sys 16 | import time 17 | 18 | 19 | # ------------------------------------------------------------------------------- 20 | def OpenPort(host, port): 21 | 22 | try: 23 | # create an INET, STREAMing socket 24 | newSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 25 | newSocket.settimeout(3) 26 | # now connect to the server on our port 27 | newSocket.connect((host, port)) 28 | return newSocket 29 | except Exception as e1: 30 | print("Error opening socket: " + str(e1)) 31 | return None 32 | 33 | 34 | # ------------------------------------------------------------------------------- 35 | if __name__ == "__main__": 36 | 37 | HelpStr = "\npython3 sockettest.py -a -p \n" 38 | HelpStr += "\n -a \n" 39 | HelpStr += " -p \n" 40 | 41 | try: 42 | opts, args = getopt.getopt(sys.argv[1:], "ha:p:", ["address=", "port="]) 43 | except getopt.GetoptError: 44 | print(HelpStr) 45 | sys.exit(2) 46 | 47 | host = None 48 | port = None 49 | for opt, arg in opts: 50 | if opt == "-h": 51 | print(HelpStr) 52 | sys.exit() 53 | elif opt in ("-a", "--address"): 54 | host = arg 55 | elif opt in ("-p", "--port"): 56 | port = arg 57 | 58 | if host == None or port == None: 59 | print(HelpStr) 60 | sys.exit(2) 61 | 62 | print( 63 | "\nLoopback testing for TCP serial port at " + host + ":" + str(port) + "...\n" 64 | ) 65 | 66 | try: 67 | 68 | # Starting serial connection 69 | Socket = OpenPort(host, int(port)) 70 | if Socket == None: 71 | print("Error creating socket") 72 | sys.exit(1) 73 | 74 | TestString = "Testing 1 2 3\n" 75 | 76 | print("write data: sent test string") 77 | Socket.sendall(TestString.encode()) 78 | print("waiting to received data....") 79 | time.sleep(0.05) 80 | ReceivedString = Socket.recv(200) 81 | 82 | Socket.close() 83 | 84 | ReceivedString = ReceivedString.decode("UTF-8") 85 | 86 | if TestString != ReceivedString: 87 | print( 88 | "FAILED: Sent data does not match receive. Received %d bytes" 89 | % len(ReceivedString) 90 | ) 91 | else: 92 | print("PASSED! Loopback successful") 93 | Socket.close() 94 | 95 | except Exception as e1: 96 | print("error communicating...: " + str(e1)) 97 | 98 | sys.exit(1) 99 | -------------------------------------------------------------------------------- /addon/gengpioledblink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------------------------- 3 | # FILE: gengpioledblink.py 4 | # PURPOSE: genmon.py support program to allow GPIO pins to drive 5 | # status LEDs 6 | # 7 | # AUTHOR: Jason G Yates 8 | # DATE: 05-Apr-2016 9 | # 10 | # MODIFICATIONS: 11 | # ------------------------------------------------------------------------------- 12 | 13 | import json 14 | import os 15 | import signal 16 | import sys 17 | import time 18 | 19 | try: 20 | # this will add the parent of the genmonlib folder to the path 21 | # if we are one level below the genmonlib parent (e.g. in the addon folder) 22 | file_root = os.path.dirname(os.path.realpath(__file__)) 23 | parent_root = os.path.abspath(os.path.join(file_root, os.pardir)) 24 | if os.path.isdir(os.path.join(parent_root, "genmonlib")): 25 | sys.path.insert(1, parent_root) 26 | 27 | from genmonlib.myclient import ClientInterface 28 | from genmonlib.myconfig import MyConfig 29 | from genmonlib.mylog import SetupLogger 30 | from genmonlib.mysupport import MySupport 31 | except Exception as e1: 32 | print( 33 | "\n\nThis program requires the modules located in the genmonlib directory in the github repository.\n" 34 | ) 35 | print( 36 | "Please see the project documentation at https://github.com/jgyates/genmon.\n" 37 | ) 38 | print("Error: " + str(e1)) 39 | sys.exit(2) 40 | 41 | import RPi.GPIO as GPIO 42 | 43 | led_pin = 12 # GPIO board pin number that LED is connected to (default value) 44 | 45 | # ---------- Signal Handler ---------------------------------------------------- 46 | def signal_handler(signal, frame): 47 | 48 | # Turn off LED before exiting 49 | GPIO.output(led_pin, GPIO.LOW) 50 | 51 | GPIO.cleanup() 52 | MyClientInterface.Close() 53 | sys.exit(0) 54 | 55 | 56 | # ---------- blink_LED --------------------------------------------------------- 57 | def blink_LED(pin, nfast): 58 | blinkdelay = 0.15 59 | 60 | GPIO.output(pin, GPIO.HIGH) 61 | time.sleep(1) 62 | GPIO.output(pin, GPIO.LOW) 63 | time.sleep(1) 64 | 65 | for i in range(nfast): 66 | GPIO.output(pin, GPIO.HIGH) 67 | time.sleep(blinkdelay) 68 | GPIO.output(pin, GPIO.LOW) 69 | time.sleep(blinkdelay) 70 | 71 | 72 | # ------------------- Command-line interface for gengpioledblink ---------------- 73 | if __name__ == "__main__": # usage program.py [server_address] 74 | 75 | try: 76 | ( 77 | console, 78 | ConfigFilePath, 79 | address, 80 | port, 81 | loglocation, 82 | log, 83 | ) = MySupport.SetupAddOnProgram("gengpioledblink") 84 | # Set the signal handler 85 | signal.signal(signal.SIGINT, signal_handler) 86 | signal.signal(signal.SIGTERM, signal_handler) 87 | 88 | conf_file = os.path.join(ConfigFilePath, "gengpioledblink.conf") 89 | if os.path.isfile(conf_file): 90 | config = MyConfig(filename=conf_file, section="gengpioledblink", log=log) 91 | 92 | led_pin = config.ReadValue("ledpin", return_type=int, default=12) 93 | 94 | MyClientInterface = ClientInterface(host=address, port=port, log=log) 95 | 96 | # setup GPIO using Board numbering 97 | GPIO.setmode(GPIO.BOARD) 98 | 99 | console.info(GPIO.RPI_INFO) 100 | 101 | GPIO.setwarnings(False) 102 | GPIO.setup(led_pin, GPIO.OUT, initial=GPIO.LOW) 103 | 104 | while True: 105 | 106 | # Get Genmon status 107 | try: 108 | TempDict = {} 109 | TempDict = json.loads( 110 | MyClientInterface.ProcessMonitorCommand("generator: monitor_json") 111 | ) 112 | 113 | if ( 114 | TempDict["Monitor"][0]["Generator Monitor Stats"][0][ 115 | "Monitor Health" 116 | ].lower() 117 | == "ok" 118 | ): 119 | blink_LED(led_pin, 5) 120 | else: 121 | blink_LED(led_pin, 2) 122 | 123 | except Exception as e1: 124 | log.error("Error getting monitor health: " + str(e1)) 125 | 126 | except Exception as e1: 127 | log.error("Error: " + str(e1)) 128 | console.error("Error: " + str(e1)) 129 | -------------------------------------------------------------------------------- /addon/genlog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------------------------- 3 | # FILE: genlog.py 4 | # PURPOSE: genmon.py support program to allow logging of generator 5 | # run time 6 | # 7 | # AUTHOR: Jason G Yates 8 | # DATE: 19-Apr-2016 9 | # 10 | # MODIFICATIONS: 11 | # ------------------------------------------------------------------------------- 12 | 13 | import datetime 14 | import getopt 15 | import os 16 | import signal 17 | import sys 18 | import time 19 | from datetime import datetime 20 | 21 | try: 22 | # this will add the parent of the genmonlib folder to the path 23 | # if we are one level below the genmonlib parent (e.g. in the addon folder) 24 | file_root = os.path.dirname(os.path.realpath(__file__)) 25 | parent_root = os.path.abspath(os.path.join(file_root, os.pardir)) 26 | if os.path.isdir(os.path.join(parent_root, "genmonlib")): 27 | sys.path.insert(1, parent_root) 28 | 29 | from genmonlib.myclient import ClientInterface 30 | from genmonlib.mylog import SetupLogger 31 | from genmonlib.mysupport import MySupport 32 | from genmonlib.program_defaults import ProgramDefaults 33 | except Exception as e1: 34 | print( 35 | "\n\nThis program requires the modules located in the genmonlib directory in the github repository.\n" 36 | ) 37 | print( 38 | "Please see the project documentation at https://github.com/jgyates/genmon.\n" 39 | ) 40 | print("Error: " + str(e1)) 41 | sys.exit(2) 42 | 43 | 44 | # ---------- Signal Handler ---------------------------------------------------- 45 | def signal_handler(signal, frame): 46 | 47 | MyClientInterface.Close() 48 | sys.exit(0) 49 | 50 | 51 | # ------------------- excel_date ------------------------------------------------ 52 | def excel_date(date1): 53 | temp = datetime(1899, 12, 30) # Note, not 31st Dec but 30th! 54 | delta = date1 - temp 55 | return str(float(delta.days) + (float(delta.seconds) / 86400)) 56 | 57 | 58 | # ------------------- Command-line interface for genlog ------------------------- 59 | def LogDataToFile(fileName, time, Event): 60 | 61 | with open(fileName, "a") as LogFile: # opens file 62 | if os.stat(fileName).st_size == 0: 63 | LogFile.write("Time,Event\n") 64 | 65 | LogFile.write(excel_date(time) + "," + Event + "\n") 66 | LogFile.flush() 67 | 68 | 69 | # ------------------- Command-line interface for genlog ------------------------- 70 | if __name__ == "__main__": 71 | 72 | address = ProgramDefaults.LocalHost 73 | fileName = "" 74 | 75 | HelpStr = "\npython genlog.py -a -f -c \n" 76 | 77 | try: 78 | ConfigFilePath = ProgramDefaults.ConfPath 79 | console = SetupLogger("genlog_console", log_file="", stream=True) 80 | 81 | port, loglocation, multi_instance = MySupport.GetGenmonInitInfo( 82 | ConfigFilePath, log=console 83 | ) 84 | 85 | if not MySupport.PermissionsOK(): 86 | console.error( 87 | "You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting." 88 | ) 89 | sys.exit(2) 90 | 91 | if MySupport.IsRunning( 92 | os.path.basename(__file__), multi_instance=multi_instance 93 | ): 94 | console.error( 95 | "The program %s is already loaded" % os.path.basename(__file__) 96 | ) 97 | sys.exit(2) 98 | 99 | opts, args = getopt.getopt( 100 | sys.argv[1:], "ha:f:c:", ["help", "address=", "filename=", "configpath="] 101 | ) 102 | except getopt.GetoptError: 103 | console.error(HelpStr) 104 | sys.exit(2) 105 | 106 | for opt, arg in opts: 107 | if opt == "-h": 108 | console.error(HelpStr) 109 | sys.exit() 110 | elif opt in ("-a", "--address"): 111 | address = arg 112 | elif opt in ("-f", "--filename"): 113 | fileName = arg 114 | fileName = fileName.strip() 115 | elif opt in ("-c", "--configpath"): 116 | ConfigFilePath = arg 117 | ConfigFilePath = ConfigFilePath.strip() 118 | 119 | console.error("Address is " + address) 120 | console.error("Output file is " + fileName) 121 | console.error("Config File Path is " + ConfigFilePath) 122 | 123 | if not len(fileName): 124 | console.error(HelpStr) 125 | sys.exit(2) 126 | 127 | log = SetupLogger("client", os.path.join(loglocation, "genlog.log")) 128 | 129 | try: 130 | # Set the signal handler 131 | signal.signal(signal.SIGINT, signal_handler) 132 | signal.signal(signal.SIGTERM, signal_handler) 133 | 134 | MyClientInterface = ClientInterface(host=address, port=port, log=log) 135 | 136 | LastEvent = "" 137 | 138 | while True: 139 | 140 | data = MyClientInterface.ProcessMonitorCommand("generator: getbase") 141 | 142 | if LastEvent != data: 143 | LastEvent = data 144 | LogDataToFile(fileName, datetime.now(), data) 145 | 146 | time.sleep(3) 147 | 148 | except Exception as e1: 149 | log.error("Error: " + str(e1)) 150 | console.error("Error: " + str(e1)) 151 | -------------------------------------------------------------------------------- /conf/genalexa.conf: -------------------------------------------------------------------------------- 1 | [genalexa] 2 | # The name for which the Echo speaker will respond. 3 | name=generator 4 | 5 | # The callback port for the echo speaker. Needs to be available 6 | port=52004 7 | -------------------------------------------------------------------------------- /conf/gencallmebot.conf: -------------------------------------------------------------------------------- 1 | 2 | [gencallmebot] 3 | # CallMeBot Notifcation type, must be either WhatsApp, Facebook, Telegram or Signal 4 | notification_type = WhatsApp 5 | 6 | # CallMeBot API Key, required for WhatsApp, Signal and Facebook 7 | api_key = 8 | 9 | # Username, required for Telegram 10 | username = 11 | 12 | # Receipient Phone Number, Must start with a "+" and inclide the country 13 | # code, but not inclduign any spaces, so eg +12121211234 14 | # Receipient Phone Number, Must start with a "+" and inclide the country 15 | # code, but not inclduign any spaces, so eg +12121211234 16 | # For signal, this must be the key sent from callmebot when enabling the 17 | # signal service with callmebot (numeric in the form 18 | # xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) 19 | recipient_number = 20 | 21 | # number of seconds to retry sending a failed message 22 | max_retry_time = 600 23 | 24 | # the number of seconds to wait before sending a failed message 25 | default_wait = 120 26 | -------------------------------------------------------------------------------- /conf/gencentriconnect.conf: -------------------------------------------------------------------------------- 1 | [gencentriconnect] 2 | 3 | # number of minutes between polls for tank data. Note, if the API is 4 | # called too often and error may occur in an attempt to limit the traffic 5 | # No more than 5 reads per day is recommended 6 | poll_frequency = 288 7 | 8 | # user ID 9 | # The user ID the sensor is assigned to. This should be a long number 10 | # with dashes that looks like this 36e551aa-c215-4c9b-8c70-ba7729687654 11 | # You can get the user ID number by contacting centriconnect support at 12 | # support@centriconnect.com. This may be available via the web app 13 | # at https://app.centriconnect.com/ in the future (possibly Fall 2025). 14 | user_id = 15 | 16 | # device ID 17 | # The ID of the sensor. This should be a long number with dashes 18 | # that looks like this 36e551aa-c215-4c9b-8c70-ba77296878cc 19 | # This number is provided with the device 20 | device_id = 21 | 22 | # device auth code 23 | # the authentication code for the device. This is provided with the device 24 | device_auth = 25 | 26 | # only set to True for debugging purposes 27 | debug = False 28 | 29 | -------------------------------------------------------------------------------- /conf/gencthat.conf: -------------------------------------------------------------------------------- 1 | [gencthat] 2 | 3 | # recommended CT sensor is Model: SCT-013-000 100A/1V Output voltage type 4 | 5 | # number of seconds between polls for sensor data. 6 | poll_frequency = 15 7 | 8 | # set strict to true to only use the CT data if the generator utility line is in 9 | # an outage. If your CTs are connected after the transfer switch (i.e. utility 10 | # and generator are monitored) the you will want to enable this setting to keep 11 | # genmon from using the CT readings when there is not an outage. 12 | strict = False 13 | -------------------------------------------------------------------------------- /conf/gencustomgpio.conf: -------------------------------------------------------------------------------- 1 | [gencustomgpio] 2 | # The interval to poll the GPIO pin state. The genmon UI only updates every 5 seconds 3 | poll_interval=5 4 | # the path location the program will write the file userdefined.json 5 | output_path=/home/pi/genmon/ 6 | groupname = Custom GPIO Inputs 7 | # only set this to true in a temperary basis as this increases writes to the SD card 8 | debug = False 9 | 10 | # NOTE: Each of the following sections will represent one GPIO input. Each input 11 | # will have the following: 12 | # [pin number] - This is the section name and must be the integer pin number 13 | # This is not the GPIO number, but the pi header pin number 14 | # This entery with brackets marks the section begining 15 | # title = "GPIO Pin 13" - This entry is the name of the GPIO pin to be displayed 16 | # activename = "Active" - This entry represents what is desplayed if the GPIO 17 | # pin is active. Must be a quoted string 18 | # inactivename = "Inactive" - This entry represents what is desplayed if the GPIO 19 | # pin is inactive. Must be a quoted string 20 | # 21 | # Add or remove pin sections to add or remove GPIO pins 22 | # 23 | # NOTE: The GPIO pin values specified must not conflict with any other program 24 | # using GPIO on the rapsberry pi. The pin numbers are not validated by the 25 | # software 26 | 27 | [13] 28 | title = GPIO Pin 13 29 | activename = Active 30 | inactivename = Inactive 31 | 32 | [11] 33 | title = GPIO Pin 11 34 | activename = On 35 | inactivename = Off 36 | 37 | -------------------------------------------------------------------------------- /conf/genemail2sms.conf: -------------------------------------------------------------------------------- 1 | 2 | [genemail2sms] 3 | # email to SMS email recipient. Must be a valid email address 4 | # see this page for your mobile carrier address formats: 5 | # https://support.teamunify.com/en/articles/227 6 | # For example : 7 | # (555) 555-5555 mobile number would send to 555555555@txt.att.net 8 | 9 | destination = 10 | -------------------------------------------------------------------------------- /conf/genexercise.conf: -------------------------------------------------------------------------------- 1 | [genexercise] 2 | 3 | # Optional. This value is the IP address of the system running the generator 4 | # monitor software. If the genexercise.py program is running on the same 5 | # system as genmon, then this parameter is not needed. 6 | monitor_address = 7 | 8 | # Exercise Type. Specify the type of exercise to perform. 9 | # Must be one of the following: 10 | # quiet, normal, transfer 11 | # The default value is normal 12 | exercise_type = normal 13 | 14 | # Hour to start the exercise. Must be 0 - 23. Default value is 12 15 | exercise_hour = 12 16 | 17 | # Minute to start the exercise. Must be 0 -59. Default value is 0 18 | exercise_minute = 0 19 | 20 | # Day of month to start the exercise if monthly. Must be 1 - 28 21 | # Default value is 1 22 | exercise_day_of_month = 1 23 | 24 | # to specifiy monthly exercise by the x weekday of the month 25 | # (i.e. 2nd Monday) set this value to 1 - 5 and use 26 | # exercise_day_of_week, otherwise use exercise_day_of_month 27 | # values other than 1 - 5 will force monthly to use exercise_day_of_month 28 | exercise_nth_day_of_month = 0 29 | 30 | # Day of the week to start the exercise if weekly or bi-weekly 31 | # The default value is Monday 32 | exercise_day_of_week = Monday 33 | 34 | # Exercise duration in minutes. Must be a floating point value between 35 | # 5 and 60 minutes. Note that when using the transfer option, this is 36 | # the time period that the transfer switch is active (does not include 37 | # warmup time). The default value is 12. 38 | exercise_duration = 12 39 | 40 | # Warm up duration. If exercise_type is transfer then this is the number 41 | # of minutes to run before the transfer switch is activated. If this value 42 | # is zero, then no warmup period is used. Maximum warmup is 30 minutes. 43 | # This value may be a floating point value. 44 | # The default value is 0, i.e. no warmup 45 | exercise_warmup = 0 46 | 47 | # Exercise frequency. Must be one of the following: 48 | # Weekly, Biweekly, Monthly 49 | # The default value is Monthly 50 | exercise_frequency = Monthly 51 | 52 | # Set to true to use the generator time, otherwise use the system time 53 | use_gen_time = False 54 | -------------------------------------------------------------------------------- /conf/gengpio.conf: -------------------------------------------------------------------------------- 1 | [gengpio] 2 | 3 | # The following assignments are for the Raspberry pi header pin numbers, not the GPIO number 4 | # set any value to zero to have this value ignored (no used) so you can free up GPIO for other uses 5 | 6 | # READY GPIO 23 (pin 16) 7 | STATUS_READY = 16 8 | # ALARM GPIO 24 (pin 18) 9 | STATUS_ALARM = 18 10 | # SERVICE DUE GPIO 25 (pin 22) 11 | STATUS_SERVICE = 22 12 | # RUNNING GPIO 7 (pin 26) 13 | STATUS_RUNNING = 26 14 | # EXERCISING GPIO 8 (pin 24) 15 | STATUS_EXERCISING = 24 16 | # OFF GPIO 9 (pin 21) 17 | STATUS_OFF = 21 18 | 19 | # Set additional GPIO based on these error codes 20 | # Genmon is reporting errors due to modbus or internal problems GPIO 2(pin3) 21 | ER_GENMON = 3 22 | # No internet connection GPIO3 (pin 5) 23 | ER_INTERNET = 5 24 | # Overspeed/Underspeed (alarms 1200-1206, 1600-1603) GPIO 5 (pin 29) 25 | ER_SPEED = 29 26 | # Low Oil (alarm 1300) GPIO 6 (pin 31) 27 | ER_LOW_OIL = 31 28 | # High Temp (alarm 1400) GPIO 13 (pin 33 29 | ER_HIGH_TEMP = 33 30 | # RPM Sensor (alarm 1500-1521) GPIO 19 (pin 35) 31 | ER_RPM_SENSE = 35 32 | # Overvoltage/Undervoltage (alarm1800-1803, 1900-1906) GPIO 26 (pin 37) 33 | ER_VOLTAGE = 37 34 | # Overcrank (alarm 1100-1101) GPIO 21 (pin 40) 35 | ER_OVERCRANK = 40 36 | # Overload (alarm 2100-2103) GPIO 20 (pin 38) 37 | ER_OVERLOAD = 38 38 | # Governor (alarm 2500-2502) GPIO 16 (pin 36) 39 | ER_GOVERNOR = 36 40 | # Evolution Air Cooled Warning GPIO 12 (pin 32) 41 | ER_WARNING = 32 42 | 43 | # Set this to a unique non conflicting GPIO pin number to enable setting 44 | # the specificed GPIO pin if the PI CPU temp goes above the defined threshold 45 | ER_PITEMP = 0 46 | 47 | # decimal value of PI CPU temp threshold. Note, this value could be 48 | # Celsius or Fahrenheit depending on the "Use Metric" setting in genmon. 49 | # recommended setting is either 70 C or 158 F if this is used to enable 50 | # enclosure cooling fan 51 | CPU_THRESHOLD_TEMP = 158 52 | 53 | # Set this to a unique non conflicting GPIO pin number to enable setting 54 | # the specificed GPIO pin at the time specificecd by PIN_EXTERNAL_SIGNAL_ON_TIME 55 | # and disable the pin at PIN_EXTERNAL_SIGNAL_OFF_TIME 56 | PIN_EXTERNAL_SIGNAL = 0 57 | 58 | # the 24 hour time and minute to enable the signal, e.g. 22:45, or 1:30 59 | PIN_EXTERNAL_SIGNAL_ON_TIME=22:00 60 | # the 24 hour time and minute to disable the signal, e.g. 22:45, or 1:30 61 | PIN_EXTERNAL_SIGNAL_OFF_TIME=8:00 62 | 63 | # Below are alternate alarm sources to use if more GPIO pins are available 64 | # Must chose from available GPIO, do not reuse any GPIO. Each GPIO used must 65 | # be unque 66 | 67 | # Controller Internal (alarm 1000s) 68 | #ER_Controller = 69 | # Ignition (alarm 2600-2669) 70 | #ER_Ignition = 71 | # Fuel Level (alarm 2680 and 2700) 72 | #ER_Low_Fuel = 73 | # Low Coolant (alarm 2720) 74 | #ER_Low_Coolant = 75 | # Battery (alarm 2750 and 2760) 76 | #ER_Battery_Problem = 77 | # Charger (alarm 2770 and 2780) 78 | #ER_Charger = 79 | 80 | # Setting debug to True will enabled more output in the log file. This is only 81 | # recommended to use when troubleshooting problems and should be set to False 82 | # in normal operations 83 | debug = False -------------------------------------------------------------------------------- /conf/gengpioin.conf: -------------------------------------------------------------------------------- 1 | [gengpioin] 2 | # Trigger GPIO on rising or falling edge. Valid values are : rising, falling, both 3 | trigger=falling 4 | 5 | # Pull up/down resistor config for inputs : valid values are : up, down, off 6 | resistorpull=up 7 | 8 | # software debounce, integer value for length of software debounce in 9 | # milliseconds 10 | bounce = 200 11 | 12 | # Optional. Set to True to use GPIO lib callbacks. Set to False to use 13 | # gengpioin.py callbacks. 14 | uselibcallbacks=True 15 | 16 | # STOP GPIO 17, pin 11 17 | INPUT_STOP = 11 18 | 19 | # START GPIO 27 20 | INPUT_START = 13 21 | 22 | # START/TRANSFER GPIO 22 23 | INPUT_START_TRANSFER = 15 24 | -------------------------------------------------------------------------------- /conf/gengpioledblink.conf: -------------------------------------------------------------------------------- 1 | [gengpioledblink] 2 | # GPIO pin # that LED is connected to that is to be blinked 3 | ledpin=12 4 | -------------------------------------------------------------------------------- /conf/genloader.conf: -------------------------------------------------------------------------------- 1 | 2 | # each module has it's own section name with the following parameters 3 | # module - python module name with no path (assumed to be the same directory 4 | # as genloader.py or in the ./addon folder) 5 | 6 | # enable - True or false, True will load the module, false will ignore the 7 | # module 8 | 9 | # hardstop - Use with caution, does not wait for the process to end gracefully 10 | # before stopping 11 | 12 | # conffile - config file name with no path (assumed to be /etc) 13 | 14 | # args - command line arguments 15 | 16 | # priority - load priority, no value is loaded last. Valid range is 0 - 100 17 | 18 | # postloaddelay - Number of seconds to delay after loading before loading 19 | # another module 20 | 21 | [genmon] 22 | module = genmon.py 23 | enable = True 24 | hardstop = False 25 | conffile = genmon.conf,mymail.conf 26 | args = 27 | priority = 0 28 | postloaddelay = 4 29 | 30 | [genserv] 31 | module = genserv.py 32 | enable = True 33 | hardstop = False 34 | conffile = genmon.conf 35 | args = 36 | priority = 1 37 | 38 | [gengpio] 39 | module = gengpio.py 40 | enable = False 41 | hardstop = False 42 | conffile = gengpio.conf 43 | args = 44 | priority = 2 45 | 46 | [gengpioin] 47 | module = gengpioin.py 48 | enable = False 49 | hardstop = False 50 | conffile = gengpioin.conf 51 | args = 52 | priority = 2 53 | 54 | [genlog] 55 | module = genlog.py 56 | enable = False 57 | hardstop = False 58 | conffile = 59 | args = -f /home/pi/genmon/LogFile.csv 60 | priority = 2 61 | 62 | [gensms] 63 | module = gensms.py 64 | enable = False 65 | hardstop = False 66 | conffile = gensms.conf 67 | args = 68 | priority = 2 69 | 70 | [gensms_modem] 71 | module = gensms_modem.py 72 | enable = False 73 | hardstop = False 74 | conffile = mymodem.conf 75 | args = 76 | priority = 2 77 | 78 | [genpushover] 79 | module = genpushover.py 80 | enable = False 81 | hardstop = False 82 | conffile = genpushover.conf 83 | args = 84 | priority = 2 85 | 86 | [gensyslog] 87 | module = gensyslog.py 88 | enable = False 89 | hardstop = False 90 | conffile = 91 | args = 92 | priority = 2 93 | 94 | [genmqtt] 95 | module = genmqtt.py 96 | enable = False 97 | hardstop = False 98 | conffile = genmqtt.conf 99 | args = 100 | priority = 2 101 | 102 | [genmqttin] 103 | module = genmqttin.py 104 | enable = False 105 | hardstop = False 106 | conffile = genmqttin.conf 107 | args = 108 | priority = 2 109 | 110 | [genslack] 111 | module = genslack.py 112 | enable = False 113 | hardstop = False 114 | conffile = genslack.conf 115 | args = 116 | priority = 2 117 | 118 | [genexercise] 119 | module = genexercise.py 120 | enable = False 121 | hardstop = False 122 | conffile = genexercise.conf 123 | args = 124 | priority = 2 125 | 126 | [genalexa] 127 | module = genalexa.py 128 | enable = False 129 | hardstop = False 130 | conffile = genalexa.conf 131 | args = 132 | priority = 2 133 | 134 | [gencentriconnect] 135 | module = gencentriconnect.py 136 | enable = False 137 | hardstop = False 138 | conffile = gencentriconnect.conf 139 | args = 140 | priority = 2 141 | 142 | [gentankutil] 143 | module = gentankutil.py 144 | enable = False 145 | hardstop = False 146 | conffile = gentankutil.conf 147 | args = 148 | priority = 2 149 | 150 | [gentankdiy] 151 | module = gentankdiy.py 152 | enable = False 153 | hardstop = False 154 | conffile = gentankdiy.conf 155 | args = 156 | priority = 2 157 | 158 | [genemail2sms] 159 | module = genemail2sms.py 160 | enable = False 161 | hardstop = False 162 | conffile = genemail2sms.conf 163 | args = 164 | priority = 2 165 | 166 | [gensnmp] 167 | module = gensnmp.py 168 | enable = False 169 | hardstop = False 170 | conffile = gensnmp.conf 171 | args = 172 | priority = 2 173 | 174 | [gentemp] 175 | module = gentemp.py 176 | enable = False 177 | hardstop = False 178 | conffile = gentemp.conf 179 | args = 180 | priority = 2 181 | 182 | [gengpioledblink] 183 | module = gengpioledblink.py 184 | enable = False 185 | hardstop = False 186 | conffile = gengpioledblink.conf 187 | args = 188 | priority = 2 189 | 190 | [gencthat] 191 | module = gencthat.py 192 | enable = False 193 | hardstop = False 194 | conffile = gencthat.conf 195 | args = 196 | priority = 2 197 | 198 | [genmopeka] 199 | module = genmopeka.py 200 | enable = False 201 | hardstop = False 202 | conffile = genmopeka.conf 203 | args = 204 | priority = 2 205 | 206 | [gencustomgpio] 207 | module = gencustomgpio.py 208 | enable = False 209 | hardstop = False 210 | conffile = gencustomgpio.conf 211 | args = 212 | priority = 2 213 | 214 | [gensms_voip] 215 | module = gensms_voip.py 216 | enable = False 217 | hardstop = False 218 | conffile = gensms_voip.conf 219 | args = 220 | priority = 2 221 | 222 | [gencallmebot] 223 | module = gencallmebot.py 224 | enable = False 225 | hardstop = False 226 | conffile = gencallmebot.conf 227 | args = 228 | priority = 2 229 | 230 | [genloader] 231 | version = 232 | -------------------------------------------------------------------------------- /conf/genmopeka.conf: -------------------------------------------------------------------------------- 1 | [genmopeka] 2 | 3 | # number of minutes between polls for tank data. 4 | poll_frequency = 60 5 | 6 | # tank address 7 | # This value is MAC address of the sensor. It must be in a format using 8 | # hex numbers separated by colons (i.e. 9a:03:2b:67:25:12). 9 | # multiple tank sensors (up to 4) may be used with commas 10 | # between each address 11 | tank_address = 12 | 13 | # specifiy the tank type 14 | # Valid types: 20_LB, 30_LB, 40_LB, 100_LB, 200_LB, 120_GAL, 120_GAL_HORIZ, 15 | # 250_GAL, 500_GAL, 1000_GAL and Custom 16 | # Custom tank type relies on user defined values of min_mm and max_mm 17 | tank_type = 18 | 19 | # optional - integer - Tank min millimeters - minimum millimeter reading of sensor 20 | # used with Custom Tank type 21 | min_mm = 22 | 23 | # optional - integer - Tank max millimeters - maximium millimeter reading of sensor 24 | max_mm = 25 | 26 | # optional boolean 27 | # this value, if true will send an email notice if the sensor batter is low or if 28 | # no Bluetooth sensors are detected. Outbound email must be setup and working 29 | # with genmon for this feature to work 30 | send_notices = False 31 | -------------------------------------------------------------------------------- /conf/genmqtt.conf: -------------------------------------------------------------------------------- 1 | [genmqtt] 2 | 3 | # Required. Address of MQTT Broker server. This value should be changed to match 4 | # the IP address of your MQTT server. 5 | mqtt_address = 192.168.1.20 6 | 7 | # Optional. This value is used if your MQTT server requires authentication. 8 | # This is the username. 9 | # NOTE: a return code of 5 when connecting to the MQTT server typically means 10 | # that the username / password was not provided or is incorrect. 11 | username = 12 | 13 | # Optional. This value is used if your MQTT server requires authentication. 14 | # This is the password. 15 | password = 16 | 17 | # Optional. This value is the IP address of the system running the generator 18 | # monitor software. If the genmqttin.py program is running on the same system as 19 | # genmon, then this parameter is not needed. 20 | monitor_address = 21 | 22 | # Optional. This parameter is the port of the MQTT server in a decimal number. 23 | # If this value is not present then 1883 the default. 24 | mqtt_port = 1883 25 | 26 | # Optional. Poll interval is the time between requesting status from genmon. 27 | # The default value is 2 seconds. You can override the default with a floating 28 | # point number. 29 | poll_interval = 2.0 30 | 31 | # Optional. Flush Interval is the time in seconds where even unchanged values 32 | # will be published to their MQTT topic. Default is a very large number that 33 | # effectively turns off flushing of unchanged values. Zero also disables 34 | # flushing 35 | flush_interval = 0 36 | 37 | # Optional. This value will be added to the beginning of the MQTT path. The 38 | # default path used is 'generator/' however you could add set root_topic=Home 39 | # to make the path be Home/generator. 40 | root_topic = 41 | 42 | # Optional. This value, if true will return numeric values in the Status 43 | # topic as a JSON string which can be converted to an object with integer 44 | # or float values. This applies to items in on the Status, Maintenance and 45 | # Outage page for Evolution and Nexus models and the Status page for 46 | # Industrial models. 47 | numeric_json = False 48 | 49 | # Optional. This value, if true will return a JSON list for any list of strings. 50 | # typically the outage log falls into this category. 51 | strlist_json = False 52 | 53 | # Optional. By default the program will attempt to export all text data that 54 | # is exported by genmon (see the web interface for details). The blacklist 55 | # entry is a way to skip some values that are updated frequently that may not 56 | # be useful in your MQTT based system. For example the modbus packet count 57 | # be suppressed from MQTT by adding "Packet Count" in the line below, or 58 | # "Platform Stats" will exclude all data in the Platform Stats section. 59 | # Multiple entries are separated by commas. 60 | blacklist = Monitor,Run Time,Monitor Time,Generator Time,External Data 61 | 62 | # Optional. Full path to Certificate Authority file. Leave empty to not 63 | # use SSL/TLS. If used the port will be forced to 8883. 64 | cert_authority_path = 65 | 66 | # Optional. Full path to the client certificate file. Leave empty to not use MTLS 67 | client_cert_path = 68 | 69 | # Optional. Full path to the client key file. Leave empty to not use MTLS 70 | client_key_path = 71 | 72 | # Optional. TLS version (Integer). Specify the TLS version used. Default is 1. 73 | # Must be 1.0, 1.1, or 1.2. This is ignored when a CA cert file is not used. 74 | tls_version = 1.0 75 | 76 | # Optional. Defines the certificate requirements that the client imposes 77 | # on the broker. Used if Certificate Authority file is used. None,Optional, 78 | # and Required are the valid options. Required is the default. 79 | cert_reqs = Required 80 | 81 | # Optional. If True then spaces will be converted to underscores "_" in the 82 | # topic path 83 | remove_spaces = False 84 | 85 | # unique identifier for each instance of genmon running. This can be any value 86 | # if you are running one instance of genmon. Otherwise each instance must be 87 | # unique 88 | client_id = genmon 89 | -------------------------------------------------------------------------------- /conf/genmqttin.conf: -------------------------------------------------------------------------------- 1 | [genmqttin] 2 | 3 | # NOTE: single entries for topics, labels, types, units, nominal_values and 4 | # maximum_value do not require comma separators 5 | 6 | # Required. a list of comma separated MQTT topics to subscribe. This add on will 7 | # monitor each topic and import the data into genmon for display. The maximum 8 | # number of topics to monitor is four 9 | topics = 10 | 11 | # Required. A list of labels that corresponded to the list of topics. These labels 12 | # will be used to display the data read from the MQTT broker in the User Interface 13 | # of genmon. Each label must be unique and the number of labels must match 14 | # the number of topics. 15 | labels = 16 | 17 | # Required. A list of comma separated units. These correspond with the list of 18 | # topics. If a unit is not used then a blank will be used to keep alignment 19 | # with the number of topics. Then number of units (including blank units) must 20 | # match the number of topics. 21 | units = 22 | 23 | # Required. A list of comma separated types. These correspond with the list of 24 | # topics. Then number of types must match the number of topics. Valid types are: 25 | # 26 | # fuel - Used for monitoring fuel gauges. The data is a percentage 0 - 100 of 27 | # the fuel tank level. Max should be set to 100. Since this is a 28 | # percentage units can be none or %. 29 | # temperature - Used for temperature sensors. Nominal and Maximum values are 30 | # sensor specific 31 | # power - Used for importing power readings into genmon. This should be used 32 | # for reporting the total power (sum of all legs) of the system. Units 33 | # should be W or kW. 34 | # current - Used for importing current readings into genmon. This should be 35 | # used for reporting the total current (sum of all legs) of the system. 36 | # Units should be A. 37 | # voltage - Used for reporting voltage. This is the total voltage for the 38 | # system. 39 | # voltageleg1 - Used for reporting a single voltage leg. This value will be 40 | # added to voltageleg2 for the total voltage. Units should be V. 41 | # voltageleg2 - Used for reporting a single voltage leg. This value will be 42 | # added to voltageleg1 for the total voltage. Units should be V. 43 | # pressure - This is for reporting a sensor pressure. 44 | # ct1 - This is used for report the current for the first leg in a multi-leg 45 | # system. Units should be A. 46 | # ct2 - This is used for report the current for the second leg in a multi-leg 47 | # system. Units should be A. 48 | # ctpower1 - This is used for report the power for the first leg in a multi-leg 49 | # system. Units should be W or kW. 50 | # ctpower2 - This is used for report the power for the first leg in a multi-leg 51 | # system. Units should be W or kW. 52 | types = 53 | 54 | # Required. The nonomal value helps the genmon UI determine how to display the 55 | # gauge colors. This is a list of comma separated units. These correspond with 56 | # the list of topics. 57 | nominal_values = 58 | 59 | # Required. The maximum value helps the genmon UI determine how to display the 60 | # gauge colors. This is a list of comma separated units. These correspond with 61 | # the list of topics. 62 | maximum_values = 63 | 64 | # Required. Address of MQTT Broker server. This value should be changed to match 65 | # the IP address of your MQTT server. 66 | mqtt_address = 192.168.1.20 67 | 68 | # Optional. This value is used if your MQTT server requires authentication. 69 | # This is the username. 70 | # NOTE: a return code of 5 when connecting to the MQTT server typically means 71 | # that the username / password was not provided or is incorrect. 72 | username = 73 | 74 | # Optional. This value is used if your MQTT server requires authentication. 75 | # This is the password. 76 | password = 77 | 78 | # Optional. This value is the IP address of the system running the generator 79 | # monitor software. If the genmqttin.py program is running on the same system as 80 | # genmon, then this parameter is not needed. 81 | monitor_address = 82 | 83 | # Optional. This parameter is the port of the MQTT server in a decimal number. 84 | # If this value is not present then 1883 the default. 85 | mqtt_port = 1883 86 | 87 | # Optional. This value will be added to the beginning of the MQTT path. The 88 | # default path used is 'generator/' however you could add set root_topic=Home 89 | # to make the path be Home/generator. 90 | root_topic = 91 | 92 | # Optional. Full path to Certificate Authority file. Leave empty to not 93 | # use SSL/TLS. If used the port will be forced to 8883. 94 | cert_authority_path = 95 | 96 | # Optional. Full path to the client certificate file. Leave empty to not use MTLS 97 | client_cert_path = 98 | 99 | # Optional. Full path to the client key file. Leave empty to not use MTLS 100 | client_key_path = 101 | 102 | # Optional. TLS version (Integer). Specify the TLS version used. Default is 1. 103 | # Must be 1.0, 1.1, or 1.2. This is ignored when a CA cert file is not used. 104 | tls_version = 1.0 105 | 106 | # Optional. Defines the certificate requirements that the client imposes 107 | # on the broker. Used if Certificate Authority file is used. None,Optional, 108 | # and Required are the valid options. Required is the default. 109 | cert_reqs = Required 110 | 111 | # unique identifier for each instance of genmon running. This can be any value 112 | # if you are running one instance of genmon. Otherwise each instance must be 113 | # unique 114 | client_id = genmon_sensor_input 115 | -------------------------------------------------------------------------------- /conf/genpushover.conf: -------------------------------------------------------------------------------- 1 | 2 | [genpushover] 3 | # APP ID 4 | # account 5 | appid = abc123 6 | 7 | # USER ID 8 | # acct 9 | userid = 123abc 10 | 11 | # Notification sound 12 | # Full list at https://pushover.net/api#sounds 13 | pushsound = updown 14 | 15 | # number of seconds to retry sending a failed message 16 | max_retry_time = 600 17 | 18 | # the number of seconds to wait before sending a failed message 19 | default_wait = 120 20 | -------------------------------------------------------------------------------- /conf/genslack.conf: -------------------------------------------------------------------------------- 1 | 2 | [genslack] 3 | # Slack Webhook URL, retrieve from Slack custom integration configuration 4 | webhook_url = https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX 5 | 6 | # Slack channel to which the message will be sent 7 | channel = 8 | 9 | # The name that appears as the user who sent the message 10 | username = GenMon 11 | 12 | # Emoji that appears as the icon of the user who sent the message i.e. :red_circle: 13 | icon_emoji = :red_circle: 14 | 15 | # Use this to make the title of the message a link i.e. link to the genmon web interface 16 | #title_link = http://URL.of.genmon:8000 17 | 18 | # number of seconds to retry sending a failed message 19 | max_retry_time = 600 20 | 21 | # the number of seconds to wait before sending a failed message 22 | default_wait = 120 23 | -------------------------------------------------------------------------------- /conf/gensms.conf: -------------------------------------------------------------------------------- 1 | 2 | [gensms] 3 | # Twilio account SID. This can be obtained from a valid Twilio 4 | # account 5 | accountsid = ACXXXXXXXXXXXXXXXXXXXXXXX 6 | 7 | # Twilio authentication token. This can be obtained from a valid 8 | # Twilio account 9 | authtoken = XXXXXXXXXXXXXXXXXX 10 | 11 | # Mobile number to send SMS message to. This can be any mobile 12 | # number. 13 | 14 | to_number = +15551234567 15 | 16 | # Number to send SMS message from. This should be a twilio phone 17 | # number 18 | from_number = +1555XXXXXXX 19 | 20 | # number of seconds to retry sending a failed message 21 | max_retry_time = 600 22 | 23 | # the number of seconds to wait before sending a failed message 24 | default_wait = 120 25 | -------------------------------------------------------------------------------- /conf/gensms_voip.conf: -------------------------------------------------------------------------------- 1 | 2 | [gensms_voip] 3 | # voip.ms account username. 4 | username = 5 | 6 | # voip.ms API password. This is NOT the account login, but rather then API 7 | # password 8 | password = 9 | 10 | # DID number for your voip.ms account to send the SMS. 11 | did = 12 | 13 | # Number to send SMS message to. This can be any mobile number 14 | destination = 15 | 16 | # number of seconds to retry sending a failed message 17 | max_retry_time = 600 18 | 19 | # the number of seconds to wait before sending a failed message 20 | default_wait = 120 21 | -------------------------------------------------------------------------------- /conf/gensnmp.conf: -------------------------------------------------------------------------------- 1 | [gensnmp] 2 | 3 | # number of seconds between polls for generator data. 4 | poll_frequency = 2 5 | 6 | # community name 7 | community = public 8 | 9 | # include more info in gensnmp.log for debugging purposes. 10 | # default to False to save on the SD card life 11 | debug = False 12 | 13 | # This is the genmon enterprise ID. 14 | enterpriseid = 58399 15 | 16 | #optional override of default snmp port to use 17 | snmpport = 161 18 | -------------------------------------------------------------------------------- /conf/gentankdiy.conf: -------------------------------------------------------------------------------- 1 | [gentankdiy] 2 | 3 | # Must be either 1 or 2. Type 1 and Type 2 are documented here: 4 | # https://github.com/jgyates/genmon/wiki/Appendix-L-Adding-a-Propane-Fuel-Gauge-to-Genmon 5 | gauge_type = 1 6 | 7 | # number of minutes between polls for tank data. 8 | poll_frequency = 60 9 | 10 | # I2C address of ADC, default is 0x48 or 72 decimal 11 | # this vaue must be a decimal integer 12 | i2c_address = 72 13 | 14 | # I2C channel, default is 1. Raspberry pi I2C on GPIO header is channel 1 15 | # This value must be a decimal integer 16 | i2c_channel = 1 17 | 18 | # Optionally support two tanks of gauge type 1, the default is 1. 19 | # Only valid data is 1, 2, 3 or 4 20 | # NOTE: This option is only for DIY gauge type 1 21 | nb_tanks = 1 22 | 23 | ######### Gauge Type 1 Settings ###################### 24 | # microvolts per step. Calibration constant for ADC conversion 25 | # This value must be a floating point value 26 | mv_per_step = 187.5 27 | 28 | # multiplier to convert volts to percentage, for 5V range this is 20.0 29 | volts_to_percent_multiplier = 20.0 30 | 31 | ######### Gauge Type 2 Settings ###################### 32 | # This is for using the Hall Effect Infineon TLE5501 E0001 TMR-based angle sensor on an R3D propane tank dial 33 | # For more info on this Hall Effect sensor see: 34 | # www.infineon.com/cms/en/product/sensor/magnetic-sensors/magnetic-position-sensors/angle-sensors/tle5501-e0001/ 35 | # Either the ADS1015 or ADS1115 can be used for the A/D converter 36 | 37 | # ADS1x15 inputs for the COS, SIN and VDD ref (optional), can be 0-4 38 | adc_COS_inp = 0 39 | adc_SIN_inp = 1 40 | adc_VDD_inp = 2 41 | 42 | # Table to convert angle to percent full for the tank, 43 | # must have at least two entries, and can have up to 10 44 | # (ang_pct_pnt_1-10) Since most dials have 45 | # 5, 10, 20, 30, 40, 50, 60, 70 and full readings, 46 | # input the angle output from the sensor for each of these readings. 47 | # DIY2TankSensorCalibrate.py can be used to easily create this table 48 | # 49 | # Angle Percent 50 | ang_pct_pnt_1 = 149.02, 5.0 51 | ang_pct_pnt_2 = 109.89, 10.0 52 | ang_pct_pnt_3 = 68.87, 20.0 53 | ang_pct_pnt_4 = 42.23, 30.0 54 | ang_pct_pnt_5 = 19.40, 40.0 55 | ang_pct_pnt_6 = 0.76, 50.0 56 | ang_pct_pnt_7 = -18.79, 60.0 57 | ang_pct_pnt_8 = -41.72, 70.0 58 | ang_pct_pnt_9 = -140.23, 100.0 59 | -------------------------------------------------------------------------------- /conf/gentankutil.conf: -------------------------------------------------------------------------------- 1 | [gentankutil] 2 | 3 | # number of minutes between polls for tank data. Note, if the API is 4 | # called too often and error may occur in an attempt to limit the traffic 5 | # by tankutility.com. 6 | poll_frequency = 60 7 | 8 | # username 9 | # The username of the online account at https://app.tankutility.com 10 | username = 11 | 12 | # password 13 | # The password of the online account 14 | password = 15 | 16 | # tank name 17 | # This value is used to match the tank name with the on-line tank name 18 | # if multiple tanks are installed. If empty then the first tank found 19 | # is used. 20 | tank_name = 21 | 22 | 23 | # tank name 2 24 | # If you have a second propane tank (and tank utility), enter the name 25 | # of your second tank here. 26 | tank_name_2 = 27 | -------------------------------------------------------------------------------- /conf/gentemp.conf: -------------------------------------------------------------------------------- 1 | [gentemp] 2 | 3 | # number of seconds between polls for generator data. 4 | poll_frequency = 2 5 | 6 | # comma separated list of device names or partial device names to exclude 7 | # when enumerating one wire temperature devices 8 | blacklist = 9 | 10 | # include more info in gentemp.log for debugging purposes. 11 | # default to False to save on the SD card life 12 | debug = False 13 | 14 | # comma separated list of labels for temperature devices found 15 | # devices excluded by blacklist will not be included. 16 | # NOTE: DS18B20 devices are enumerated first, then type K thermocouples are 17 | # enumerated. Device labels are in that order. 18 | device_labels = 19 | 20 | # comma separated list of maximum values for each sensor. The order must 21 | # match the device_lables list. This value is used to set the bounds on the 22 | # gauge. Leave blank to disable the display of the guage 23 | device_max_values = 24 | 25 | # comma separated list of nominal values for each sensor. The order must 26 | # match the device_lables list. This value is used to set the bounds on the 27 | # gauge. Leave blank to disable the display of the guage 28 | device_nominal_values = 29 | 30 | # optional. comma separated list of minimal values for each sensor. The order must 31 | # match the device_lables list. This value is used to set the bounds on the 32 | # gauge. If this parameter is not used all minumum values are assumed to be zero 33 | device_min_values = 34 | 35 | # use metric units in diplay 36 | use_metric = False 37 | -------------------------------------------------------------------------------- /conf/mymail.conf: -------------------------------------------------------------------------------- 1 | [MyMail] 2 | 3 | # optionally disable email use by the program. set to true to disable all email functionality 4 | disableemail = false 5 | 6 | # optionally disable receiving mail 7 | disableimap = true 8 | 9 | # optionally disable sending mail 10 | disablesmtp = false 11 | 12 | # The password for the email account used for sending and receiving email 13 | email_pw = mypassword 14 | 15 | # the email account 16 | email_account = mysender@gmail.com 17 | 18 | # address that email are sent to 19 | email_recipient = myrecipent@gmail.com 20 | 21 | # the email from which the emails are sent (sender email address) 22 | sender_account = no-reply@gmail.com 23 | 24 | # optional, name of the sender, i.e. Genmon or John Doe 25 | sender_name = Genmon 26 | 27 | # the SMTP mail server used for sending email, leave empty to disable SMTP, i.e. "smtp_server =" 28 | smtp_server = smtp.gmail.com 29 | 30 | # the IMAP server address used for receiving email, leave empty to disable IMAP, i.e. "imap_server =" 31 | imap_server = imap.gmail.com 32 | 33 | # the SMTP port used on the SMTP server for sending email 34 | # Note about ports and email security: typically port 587 is used for 35 | # TLS and port 465 is used for SSL 36 | smtp_port = 587 37 | 38 | # use SSL encryption to send emails 39 | ssl_enabled = false 40 | 41 | # do not use TLS encryption if true, the default value is false (use TLS). 42 | # This is parameter ignored if ssl_enable is true. Enabling this and disabling 43 | # SSL encryption will result in no SMTP encryption. 44 | tls_disable = false 45 | 46 | # optionally disable smtp authentication disabling this will result in no SMTP authentication 47 | smtpauth_disable = false 48 | 49 | # use BCC instead of To for sending mail 50 | usebcc = False 51 | 52 | # extend wait time in seconds on errors 53 | extend_wait = 0 54 | -------------------------------------------------------------------------------- /conf/mymodem.conf: -------------------------------------------------------------------------------- 1 | 2 | [MyModem] 3 | # (required) Mobile number to send SMS message. This can be any mobile 4 | # number. 5 | recipient = 5551234567 6 | 7 | # (Optional) set to true to log at commands to a file 8 | log_at_commands = True 9 | 10 | # modem type - select the type of modem used. 11 | # For future use. Presently "LTEPiHat" is the only option 12 | modem_type = LTEPiHat 13 | 14 | # port , serial port used. This is the serial device to send AT commands to 15 | # the modem. This *must* be different from the serial port used by the 16 | # generator monitor software. 17 | port = /dev/ttyAMA0 18 | 19 | # port baud rate. This is the data rate of the serial port. 20 | rate = 115200 21 | 22 | # message level. Currently all SMS messages are the same level. This option 23 | # is not used. 24 | message_level = error 25 | -------------------------------------------------------------------------------- /data/EvoAC2_Fuel.txt: -------------------------------------------------------------------------------- 1 | #Reg0019,KW,Fuel,Hz,50%,Rate 50%,100%,Rate 100%,Units 2 | # Evo2 3 | 22,16,Propane,60,0.5,1.70,1,2.99,gal 4 | 22,16,Natural Gas,60,0.5,182,1,245,cubic feet 5 | 6 | 5,8,Propane,60,0.5,0.94,1,1.68,gal 7 | 5,8,Natural Gas,60,0.5,77,1,139,cubic feet 8 | 1,9,Propane,60,0.5,0.87,1,1.37,gal 9 | 1,9,Natural Gas,60,0.5,90,1,120,cubic feet 10 | 15,11,Propane,60,0.5,1.22,1,1.97,gal 11 | 15,11,Natural Gas,60,0.5,107,1,159,cubic feet 12 | # Evo2 13 | 21,24,Propane,60,0.5,2.53,1,3.90,gal 14 | 21,24,Natural Gas,60,0.5,203,1,306,cubic feet 15 | 16 | # Evo2 17 | 24,26,Propane,60,0.5,2.06,1,3.63,gal 18 | 24,26,Natural Gas,60,0.5,188,1,333,cubic feet 19 | 20 | 7,13,Propane,60,0.5,1.55,1,2.18,gal 21 | 7,13,Natural Gas,60,0.5,156,1,220,cubic feet 22 | 2,14,Propane,60,0.5,1.56,1,2.3,gal 23 | 2,14,Natural Gas,60,0.5,156,1,220,cubic feet 24 | 25 | # Evo2 26 | 8,22,Propane,60,0.5,1.59,1,2.51,gal 27 | 8,22,Natural Gas,60,0.5,228,1,327,cubic feet 28 | 29 | # Evo 2 50Hz 3 phase export 30 | 11,20,Propane,50,0.5,2.39,1,3.56,gal 31 | 11,20,Natural Gas,50,0.5,219,1,307,cubic feet 32 | 33 | 9,16,Propane,60,0.5,2.52,1,2.94,gal 34 | 9,16,Natural Gas,60,0.5,218,1,309,cubic feet 35 | 3,17,Propane,60,0.5,1.99,1,3.57,gal 36 | 3,17,Natural Gas,60,0.5,192,1,312,cubic feet 37 | 4,20,Propane,60,0.5,2.37,1,3.56,gal 38 | 4,20,Natural Gas,60,0.5,204,1,301,cubic feet 39 | 10,20,Propane,60,0.5,1.79,1,3.46,gal 40 | 10,20,Natural Gas,60,0.5,150,1,282,cubic feet 41 | 42 | # Evo2 - Home Guardian - 22kW - Source: Manual #0L6630 43 | 17,22,Propane,60,0.5,2.53,1,3.90,gal 44 | 17,22,Natural Gas,60,0.5,228,1,327,cubic feet 45 | 46 | # TODO 47 | 32,20,Propane,60,0.5,2.39,1,3.56,gal 48 | 32,20,Natural Gas,60,0.5,219,1,307,cubic feet 49 | 12,8VA,Propane,50,0.5,0.9,1,1.52,gal 50 | 12,8VA,Natural Gas,50,0.5,83,1,138,cubic feet 51 | 13,10VA,Propane,50,0.5,1.18,1,1.92,gal 52 | 13,10VA,Natural Gas,50,0.5,124,1,195,cubic feet 53 | 14,13VA,Propane,50,0.5,1.52,1,2.52,gal 54 | 14,13VA,Natural Gas,50,0.5,146,1,225,cubic feet 55 | 56 | 18,18,Propane,60,0.5,1.70,1,3.02,gal 57 | 18,18,Natural Gas,60,0.5,169,1,247,cubic feet 58 | 59 | 23,14,Propane,60,0.5,1.81,1,3.07,gal 60 | 23,14,Natural Gas,60,0.5,195,1,256,cubic feet 61 | -------------------------------------------------------------------------------- /data/EvoAC_Fuel.txt: -------------------------------------------------------------------------------- 1 | #Reg0019,KW,Fuel,Hz,50%,Rate 50%,100%,Rate 100%,Units 2 | 22,7.5,Propane,60,0.5,0.87,1,1.42,gal 3 | 22,7.5,Natural Gas,60,0.5,73,1,117,cubic feet 4 | 5,8,Propane,60,0.5,0.94,1,1.68,gal 5 | 5,8,Natural Gas,60,0.5,77,1,139,cubic feet 6 | 1,9,Propane,60,0.5,0.87,1,1.37,gal 7 | 1,9,Natural Gas,60,0.5,90,1,120,cubic feet 8 | 15,11,Propane,60,0.5,1.22,1,1.97,gal 9 | 15,11,Natural Gas,60,0.5,107,1,159,cubic feet 10 | 21,11,Propane,60,0.5,1.18,1,1.92,gal 11 | 21,11,Natural Gas,60,0.5,124,1,195,cubic feet 12 | 7,13,Propane,60,0.5,1.55,1,2.18,gal 13 | 7,13,Natural Gas,60,0.5,156,1,220,cubic feet 14 | 2,14,Propane,60,0.5,1.56,1,2.3,gal 15 | 2,14,Natural Gas,60,0.5,156,1,220,cubic feet 16 | 8,15,Propane,60,0.5,1.59,1,2.51,gal 17 | 8,15,Natural Gas,60,0.5,173,1,245,cubic feet 18 | 11,15,Propane,60,0.5,1.9,1,3.19,gal 19 | 11,15,Natural Gas,60,0.5,193,1,312,cubic feet 20 | 9,16,Propane,60,0.5,2.52,1,2.94,gal 21 | 9,16,Natural Gas,60,0.5,218,1,309,cubic feet 22 | 3,17,Propane,60,0.5,1.99,1,3.57,gal 23 | 3,17,Natural Gas,60,0.5,192,1,312,cubic feet 24 | 4,20,Propane,60,0.5,2.37,1,3.56,gal 25 | 4,20,Natural Gas,60,0.5,204,1,301,cubic feet 26 | 10,20,Propane,60,0.5,1.79,1,3.46,gal 27 | 10,20,Natural Gas,60,0.5,150,1,282,cubic feet 28 | 17,22,Propane,60,0.5,2.53,1,3.9,gal 29 | 17,22,Natural Gas,60,0.5,228,1,327,cubic feet 30 | 32,20,Propane,60,0.5,2.39,1,3.56,gal 31 | 32,20,Natural Gas,60,0.5,219,1,307,cubic feet 32 | 12,8VA,Propane,50,0.5,0.9,1,1.52,gal 33 | 12,8VA,Natural Gas,50,0.5,83,1,138,cubic feet 34 | 13,10VA,Propane,50,0.5,1.18,1,1.92,gal 35 | 13,10VA,Natural Gas,50,0.5,124,1,195,cubic feet 36 | 14,13VA,Propane,50,0.5,1.52,1,2.52,gal 37 | 14,13VA,Natural Gas,50,0.5,146,1,225,cubic feet 38 | -------------------------------------------------------------------------------- /data/EvoLC45_Fuel.txt: -------------------------------------------------------------------------------- 1 | #KW,Fuel,25%,Rate 25%,50%,Rate 50%,75%,Rate 75%,100%,Rate 100%,Units 2 | 48,Propane,0.25,2.88,0.5,4.16,0.75,5.28,1,6.61,gal 3 | 48,Natural Gas,0.25,201,0.5,336,0.75,442,1,604,cubic feet 4 | 60,Propane,0.25,2.1,0.5,4.4,0.75,6.8,1,8.4,gal 5 | 60,Natural Gas,0.25,257,0.5,432,0.75,618,1,808,cubic feet 6 | 80,Propane,0.25,2.6,0.5,5.7,0.75,8.3,1,10.8,gal 7 | 80,Natural Gas,0.25,292,0.5,534,0.75,799,1,1063,cubic feet -------------------------------------------------------------------------------- /data/EvoLCParam.txt: -------------------------------------------------------------------------------- 1 | #kW,Volts,Frequency,Phase,Parameter Group,Voltage Code,Emission,Unit Voltage Code,Engine,Fuel,Fuel Consumption(3), units 2 | # Unit Voltage Code: A = 120/240 1 Phase, G = 120 /208 3 Phase, J = 120/240 3 Phase 3 | # K = 277/480 3 Phase, M= 110/220 1 Phase 50Hz, R = 231/400 3 Phase 4 | 12,220,50,1,10,12312,N,M,2.3 L,Diesel,0.105,0.547,1.64,gal 5 | 15,240,60,1,5,24,N,A,2.3 L,Diesel,0.015,0.251,0.24,gal 6 | 15,208,60,3,5,2072,N,G,2.3 L,Diesel,0.015,0.251,0.24,gal 7 | 15,240,60,3,5,4120,N,J,2.3 L,Diesel,0.015,0.251,0.24,gal 8 | 16,220,50,1,7,12312,N,M,2.3 L,Diesel,0.2325,0.3685,2.2825,gal 9 | 20,240,60,1,2,24,N,A,2.3 L,Diesel,0.02,0.34,0.305,gal 10 | 20,208,60,3,2,2072,N,G,2.3 L,Diesel,0.02,0.34,0.305,gal 11 | 20,240,60,3,2,4120,N,J,2.3 L,Diesel,0.02,0.34,0.305,gal 12 | 22,240,60,1,17,24,N,A,2.4 L,NG/LPV,-0.1,1.26,-0.05,gal 13 | 22,208,60,3,17,2057,N,G,2.4 L,NG/LPV,-0.1,1.26,-0.05,gal 14 | 22,240,60,3,17,4112,N,J,2.4 L,NG/LPV,-0.1,1.26,-0.05,gal 15 | 24,220,50,1,8,12312,N,M,2.4 L,Diesel,0.3775,0.3855,2.9075,gal 16 | 24,400,50,3,8,10264,N,R,2.4 L,Diesel,0.3775,0.3855,2.9075,gal 17 | 25,240,60,1,14,16,N,A,1.5 L,NG/LPV,0.075,0.235,2.575,gal 18 | 25,208,60,3,14,2064,N,G,1.5 L,NG/LPV,0.075,0.235,2.575,gal 19 | 25,240,60,3,14,4112,N,J,1.5 L,NG/LPV,0.075,0.235,2.575,gal 20 | 27,240,60,1,15,24,N,A,2.4 L,NG/LPV,-0.05,1.19,-0.05,gal 21 | 27,208,60,3,15,2072,N,G,2.4 L,NG/LPV,-0.05,1.19,-0.05,gal 22 | 27,240,60,3,15,4112,N,J,2.4 L,NG/LPV,-0.05,1.19,-0.05,gal 23 | 30,240,60,1,3,24,N,A,2.4 L,Diesel,0.0625,0.2845,0.5875,gal 24 | 30,240,60,1,21,24,N,A,1.5 L,NG/LPV,0.025,0.805,1.775,gal 25 | 30,208,60,3,3,2072,N,G,2.4 L,Diesel,0.0625,0.2845,0.5875,gal 26 | 30,208,60,3,21,2072,N,G,1.5 L,NG/LPV,,0.025,0.805,1.775,gal 27 | 30,240,60,3,3,4120,N,J,2.4 L,Diesel,0.0625,0.2845,0.5875,gal 28 | 30,240,60,3,21,4107,N,J,1.5 L,NG/LPV,,0.025,0.805,1.775,gal 29 | 30,480,60,3,3,6168,N,K,2.4 L,Diesel,0.0625,0.2845,0.5875,gal 30 | 32,240,60,1,20,16,N,A,2.4 L,NG/LPV,0.025,0.845,-0.075,gal 31 | 32,208,60,3,20,2064,N,G,2.4 L,NG/LPV,0.025,0.845,-0.075,gal 32 | 32,240,60,3,20,4112,N,J,2.4 L,NG/LPV,0.025,0.845,-0.075,gal 33 | 32,480,60,3,20,6155,N,K,2.4 L,NG/LPV,0.025,0.845,-0.075,gal 34 | 36,240,60,1,19,24,N,A,2.4 L,NG/LPV,0.05,1.63,0.65,gal 35 | 36,208,60,3,19,2064,N,G,2.4 L,NG/LPV,0.05,1.63,0.65,gal 36 | 36,240,60,3,19,4112,N,J,2.4 L,NG/LPV,0.05,1.63,0.65,gal 37 | 36,480,60,3,19,6155,N,K,2.4 L,NG/LPV,0.05,1.63,0.65,gal 38 | 38,240,60,1,12,16,N,A,2.4 L,NG/LPV,0.0002,1.1591,0.5507,gal 39 | 38,208,60,3,12,2064,N,G,2.4 L,NG/LPV,0.0002,1.1591,0.5507,gal 40 | 38,240,60,3,12,4112,N,J,2.4 L,NG/LPV,0.0002,1.1591,0.5507,gal 41 | 38,480,60,3,12,6155,N,K,2.4 L,NG/LPV,0.0002,1.1591,0.5507,gal 42 | 40,220,50,1,9,12313,N,M,3.4 L,Diesel,0.1025,2.4845,1.9975,gal 43 | 40,400,50,3,9,10264,N,R,3.4 L,Diesel,0.1025,2.4845,1.9975,gal 44 | 45,240,60,1,18,24,N,A,2.4 L,NG/LPV,0.05,1.63,0.65,gal 45 | 45,240,60,1,18,32792,Y,A,2.4 L,NG/LPV,0.05,1.63,0.65,gal 46 | 45,208,60,3,18,2064,N,G,2.4 L,NG/LPV,0.05,1.63,0.65,gal 47 | 45,208,60,3,18,34832,Y,G,2.4 L,NG/LPV,0.05,1.63,0.65,gal 48 | 45,240,60,3,18,4112,N,J,2.4 L,NG/LPV,0.05,1.63,0.65,gal 49 | 45,240,60,3,18,36880,Y,J,2.4 L,NG/LPV,0.05,1.63,0.65,gal 50 | 45,480,60,3,18,6155,N,K,2.4 L,NG/LPV,0.05,1.63,0.65,gal 51 | 45,480,60,3,18,38923,Y,K,2.4 L,NG/LPV,0.05,1.63,0.65,gal 52 | 48,240,60,1,4,24,N,A,3.4 L,Diesel,0.03,0.73,0.585,gal 53 | 48,240,60,1,13,26,N,A,5.4 L,NG/LPV,0.045,1.681,0.475,gal 54 | 48,240,60,1,13,32794,Y,A,5.4 L,NG/LPV,0.045,1.681,0.475,gal 55 | 48,208,60,3,13,2072,N,G,5.4 L,NG/LPV,0.045,1.681,0.475,gal 56 | 48,208,60,3,13,34840,Y,G,5.4 L,NG/LPV,0.045,1.681,0.475,gal 57 | 48,240,60,3,13,4112,N,J,5.4 L,NG/LPV,0.045,1.681,0.475,gal 58 | 48,240,60,3,13,36880,Y,J,5.4 L,NG/LPV,0.045,1.681,0.475,gal 59 | 48,480,60,3,13,6156,N,K,5.4 L,NG/LPV,0.045,1.681,0.475,gal 60 | 48,480,60,3,13,38924,Y,K,5.4 L,NG/LPV,0.045,1.681,0.475,gal 61 | 50,208,60,3,4,2072,N,G,3.4 L,Diesel,0.03,0.73,0.585,gal 62 | 50,240,60,3,4,4120,N,J,3.4 L,Diesel,0.03,0.73,0.585,gal 63 | 50,480,60,3,4,6168,N,K,3.4 L,Diesel,0.03,0.73,0.585,gal 64 | 60,240,60,1,16,14,N,A,2.4 L,NG/LPV,-0.075,2.465,0.325,gal 65 | 60,208,60,3,16,2064,N,G,2.4 L,NG/LPV,-0.075,2.465,0.325,gal 66 | 60,240,60,3,16,4112,N,J,2.4 L,NG/LPV,-0.075,2.465,0.325,gal 67 | 60,480,60,3,16,6156,N,K,2.4 L,NG/LPV,-0.075,2.465,0.325,gal 68 | #kW,Volts,Frequency,Phase,Parameter Group,Voltage Code,Emission,Unit Voltage Code,Engine,Fuel,Fuel Consumption(3), units 69 | #4.5L 70 | 48,240,60,1,1,27,N,A,4.5 L,NG/LPV,0.045,1.681,0.475,gal 71 | 48,208,60,3,1,2047,N,G,4.5 L,NG/LPV,0.045,1.681,0.475,gal 72 | 48,240,60,3,1,4124,N,J,4.5 L,NG/LPV,0.045,1.681,0.475,gal 73 | 48,480,60,3,1,6172,N,K,4.5 L,NG/LPV,0.045,1.681,0.475,gal 74 | 75 | 60,240,60,1,11,3,N,A,4.5 L,NG/LPV,0.045,1.681,0.475,gal 76 | 60,208,60,3,11,2051,N,G,4.5 L,NG/LPV,0.045,1.681,0.475,gal 77 | 60,240,60,3,11,4098,N,J,4.5 L,NG/LPV,0.045,1.681,0.475,gal 78 | 60,480,60,3,11,6176,N,K,4.5 L,NG/LPV,0.045,1.681,0.475,gal 79 | 80 | 80,240,60,1,7,27,N,A,4.5 L,NG/LPV,0.045,1.681,0.475,gal 81 | 80,208,60,3,7,2051,N,G,4.5 L,NG/LPV,0.045,1.681,0.475,gal 82 | 80,240,60,3,7,4099,N,J,4.5 L,NG/LPV,0.045,1.681,0.475,gal 83 | 80,480,60,3,7,6146,N,K,4.5 L,NG/LPV,0.045,1.681,0.475,gal 84 | -------------------------------------------------------------------------------- /data/EvoLC_Fuel.txt: -------------------------------------------------------------------------------- 1 | #KW,Fuel,25%,Rate 25%,50%,Rate 50%,75%,Rate 75%,100%,Rate 100%,Units 2 | 12,Diesel,0.25,2.27,0.5,3.22,0.75,4.16,1,5.53,gal 3 | 15,Diesel,0.25,0.51,0.5,0.79,0.75,1.14,1,1.48,gal 4 | 16,Diesel,0.25,2.9,0.5,3.9,0.75,5.53,1,7.46,gal 5 | 20,Diesel,0.25,0.67,0.5,1.05,0.75,1.52,1,1.98,gal 6 | 24,Diesel,0.25,3.67,0.5,5.19,0.75,7.46,1,10.49,gal 7 | 30,Diesel,0.25,0.92,0.5,1.45,0.75,1.96,1,2.74,gal 8 | 40,Diesel,0.25,4.6,0.5,7.33,0.75,10.42,1,13.56,gal 9 | 48,Diesel,0.25,1.35,0.5,2.15,0.75,3.06,1,3.98,gal 10 | 22,Propane,0.25,1.1,0.5,2.1,0.75,2.8,1,3.4,gal 11 | 22,Natural Gas,0.25,100,0.5,190,0.75,255,1,316,cubic feet 12 | 25,Propane,0.25,2.9,0.5,3.3,0.75,4,1,4.7,gal 13 | 25,Natural Gas,0.25,220,0.5,297,0.75,362,1,430,cubic feet 14 | 27,Propane,0.25,1.2,0.5,2.1,0.75,3.1,1,3.9,gal 15 | 27,Natural Gas,0.25,108,0.5,197,0.75,287,1,359,cubic feet 16 | 30,Propane,0.25,2.6,0.5,3.5,0.75,4.4,1,5.4,gal 17 | 30,Natural Gas,0.25,240,0.5,320,0.75,400,1,492,cubic feet 18 | 32,Propane,0.25,1.7,0.5,2.7,0.75,3.7,1,4.6,gal 19 | 32,Natural Gas,0.25,144,0.5,226,0.75,298,1,375,cubic feet 20 | 36,Propane,0.25,2.3,0.5,4.2,0.75,5.9,1,8,gal 21 | 36,Natural Gas,0.25,210,0.5,380,0.75,545,1,730,cubic feet 22 | 38,Propane,0.25,1.7,0.5,2.9,0.75,4,1,5.201,gal 23 | 38,Natural Gas,0.25,162,0.5,255,0.75,345,1,437,cubic feet 24 | 45,Propane,0.25,2.3,0.5,4.2,0.75,5.9,1,8,gal 25 | 45,Natural Gas,0.25,210,0.5,380,0.75,545,1,730,cubic feet 26 | 48,Propane,0.25,2.16,0.5,4.14,0.75,5.8,1,7.96,gal 27 | 48,Natural Gas,0.25,204,0.5,392,0.75,547,1,756,cubic feet 28 | 60,Propane,0.25,2.7,0.5,5,0.75,7,1,9,gal 29 | 60,Natural Gas,0.25,267,0.5,483,0.75,672,1,862,cubic feet 30 | -------------------------------------------------------------------------------- /data/NexusLCParam.txt: -------------------------------------------------------------------------------- 1 | #kW,Volts,Frequency,Phase,Parameter Group,Voltage Code,Emission,Unit Voltage Code,Engine 2 | 22,240,60,1,3,17,N,A,2.4 L 3 | 22,208,60,3,3,2057,N,G,2.4 L 4 | 22,240,60,3,3,4112,N,J,2.4 L 5 | 22,220,50,1,10,12299,N,M,2.4 L 6 | 25,240,60,1,1,16,N,A,1.6 L 7 | 25,208,60,3,1,2064,N,G,1.6 L 8 | 25,240,60,1,15,16,N,A,1.5 L 9 | 25,208,60,3,15,2064,N,G,1.5 L 10 | 25,240,60,3,15,4107,N,J,1.5 L 11 | 25,240,60,3,1,4107,N,J,1.6 L 12 | 27,240,60,1,3,11,N,A,2.4 L 13 | 27,208,60,3,3,2064,N,G,2.4 L 14 | 27,240,60,3,3,4112,N,J,2.4 L 15 | 27,400,50,3,10,10247,N,R,2.4 L 16 | 30,240,60,1,15,16,N,A,1.5 L 17 | 30,208,60,3,15,2064,N,G,1.5 L 18 | 30,240,60,3,15,4113,N,J,1.5 L 19 | 30,240,60,1,1,11,N,A,1.6 L 20 | 30,208,60,3,1,2059,N,G,1.6 L 21 | 30,240,60,3,1,4112,N,J,1.6 L 22 | 36,240,60,1,6,16,N,A,2.4 L 23 | 36,208,60,3,6,2064,N,G,2.4 L 24 | 36,240,60,3,6,4112,N,J,2.4 L 25 | 36,480,60,3,6,6160,N,K,2.4 L 26 | 35,240,60,1,6,16,N,A,2.4 L 27 | 35,208,60,3,6,2064,N,G,2.4 L 28 | 35,240,60,3,6,4112,N,J,2.4 L 29 | 35,480,60,3,6,6160,N,K,2.4 L 30 | 48,240,60,1,2,32784,Y,A,4.2 L 31 | 48,240,60,1,2,16,N,A,4.2 L 32 | 48,208,60,3,2,2064,N,G,4.2 L 33 | 48,208,60,3,2,34832,Y,G,4.2 L 34 | 48,240,60,3,2,4112,N,J,4.2 L 35 | 48,240,60,3,2,36875,Y,J,4.2 L 36 | 48,480,60,3,2,6156,N,K,4.2 L 37 | 48,480,60,3,2,38923,Y,K,4.2 L 38 | 48,240,60,1,19,16,N,A,5.4 L 39 | 48,240,60,1,19,32784,Y,A,5.4 L 40 | 48,208,60,1,19,2071,N,G,5.4 L 41 | 48,240,60,1,19,4113,N,J,5.4 L 42 | 48,480,60,3,19,6144,N,K,5.4 L 43 | 48,208,60,3,19,34832,Y,G,5.4 L 44 | 48,240,60,3,19,36875,Y,J,5.4 L 45 | 48,480,60,3,19,38923,Y,K,5.4 L 46 | 45,240,60,1,7,32779,Y,A,2.4 L 47 | 45,240,60,1,7,11,N,A,2.4 L 48 | 45,240,60,1,7,32779,Y,A,2.4 L 49 | 45,208,60,3,7,34833,Y,G,2.4 L 50 | 45,208,60,3,7,2064,N,G,2.4 L 51 | 45,240,60,3,7,36880,Y,J,2.4 L 52 | 45,240,60,3,7,4112,N,J,2.4 L 53 | 45,480,60,3,7,38928,Y,K,2.4 L 54 | 45,480,60,3,7,6155,N,K,2.4 L 55 | 45,240,60,1,2,16,Y,A,4.2 L 56 | 45,208,60,3,2,2064,N,G,4.2 L 57 | 45,480,60,3,2,2064,N,K,4.2 L 58 | 45,240,60,1,19,16,N,A,5.4 L 59 | 45,240,60,1,19,32784,Y,A,5.4 L 60 | 45,208,60,1,19,2071,Y,G,5.4 L 61 | 45,240,60,1,19,4113,N,J,5.4 L 62 | 45,480,60,3,19,6144,N,K,5.4 L 63 | 60,240,60,1,8,16,N,A,2.4 L 64 | 60,208,60,3,8,2064,N,G,2.4 L 65 | 60,240,60,3,8,4112,N,J,2.4 L 66 | 60,480,60,3,8,6156,N,K,2.4 L 67 | 70,240,60,1,13,21,N,A,6.8 L 68 | 70,240,60,1,13,32789,Y,A,6.8 L 69 | 70,208,60,3,13,2071,N,G,6.8 L 70 | 70,208,60,3,13,34839,Y,G,6.8 L 71 | 70,240,60,3,13,36875,Y,J,6.8 L 72 | 70,240,60,3,13,4105,N,J,6.8 L 73 | 70,480,60,3,13,38913,Y,K,6.8 L 74 | 70,480,60,3,13,6145,N,K,6.8 L 75 | 80,240,60,1,14,17,N,A,4.6 L 76 | 80,208,60,3,14,2053,N,G,4.6 L 77 | 80,240,60,3,14,4101,N,J,4.6 L 78 | 80,480,60,3,14,6146,N,K,4.6 L 79 | 80,240,60,1,20,0,N,A,5.4 L 80 | 80,208,60,3,20,2048,N,G,5.4 L 81 | 80,240,60,3,20,4096,N,J,5.4 L 82 | 80,480,60,3,20,6145,N,K,5.4 L 83 | 100,240,60,1,12,32785,Y,A,6.8 L 84 | 100,208,60,3,12,34816,Y,G,6.8 L 85 | 100,240,60,3,12,36864,Y,J,6.8 L 86 | 100,240,480,3,12,38919,Y,K,6.8 L 87 | 130,240,60,1,11,32785,Y,A,6.8 L 88 | 130,208,60,3,11,34827,Y,G,6.8 L 89 | 130,240,60,3,11,36875,Y,J,6.8 L 90 | 130,480,60,3,11,38934,Y,K,6.8 L 91 | 150,240,60,1,9,32785,Y,A,6.8 L 92 | 150,208,60,3,9,34833,Y,G,6.8 L 93 | 150,240,60,3,9,36880,Y,J,6.8 L 94 | 150,480,60,3,9,38932,Y,K,6.8 L 95 | -------------------------------------------------------------------------------- /data/commands/EvoLC_commands.json: -------------------------------------------------------------------------------- 1 | { 2 | "buttons":[ 3 | { 4 | "information": "This file is used for the buttons on an Evolution Liquid Cooled controller", 5 | "onewordcommand" : "resetmaintwarn", 6 | "title" : "Reset Maintenance Warnings", 7 | "command_sequence" : [ 8 | { 9 | "reg": "0003", 10 | "value": "0008" 11 | } 12 | ] 13 | }, 14 | { 15 | "onewordcommand" : "resetmaintperiods", 16 | "title" : "Reset Maintenance Periods", 17 | "command_sequence" : [ 18 | { 19 | "reg": "0003", 20 | "value": "0009" 21 | } 22 | ] 23 | }, 24 | { 25 | "onewordcommand" : "exerciseduration", 26 | "title" : "Exercise Duration", 27 | "command_sequence" : [ 28 | { 29 | "reg": "023e", 30 | "input_title": "Minutes", 31 | "type": "int", 32 | "length": 2, 33 | "bounds_regex":"^(?:([1][2-9])|([2-5][0-9])|([6][0]))$", 34 | "tooltip": "The duration of the exercise cycle. This must be a whole number between 12 and 60 minutes." 35 | } 36 | ] 37 | }, 38 | { 39 | "onewordcommand" : "startupdelay", 40 | "title" : "Start Up Delay", 41 | "command_sequence" : [ 42 | { 43 | "reg": "0239", 44 | "input_title": "Seconds", 45 | "type": "int", 46 | "length": 2, 47 | "bounds_regex":"^([5-9]|[1-9][0-9]{1,2}|1[0-4][0-9]{2}|1500)$", 48 | "tooltip": "The delay between the loss of utility power and the cranking of the generator. This must be a whole number between 5 and 1500 seconds." 49 | } 50 | ] 51 | }, 52 | { 53 | "onewordcommand" : "warmupdelay", 54 | "title" : "Warm Up Delay", 55 | "command_sequence" : [ 56 | { 57 | "reg": "0238", 58 | "input_title": "Seconds", 59 | "type": "int", 60 | "length": 2, 61 | "bounds_regex":"^([2-9]|[1-9][0-9]{1,2}|1[0-4][0-9]{2}|1500)$", 62 | "tooltip": "The delay between the start of the generator and the activation of the transfer switch when utility power has been lost. This must be a whole number between 2 and 1500 seconds." 63 | } 64 | ] 65 | }, 66 | { 67 | "onewordcommand" : "thresholdvolts", 68 | "title" : "Threshold Volts", 69 | "command_sequence" : [ 70 | { 71 | "reg": "0011", 72 | "input_title": "Volts", 73 | "type": "int", 74 | "length": 2, 75 | "bounds_regex":"^([0-9]|[1-9][0-9]|[12][0-9]{2}|3[0-3][0-9]|34[0-2])$", 76 | "tooltip": "The utility voltage that denotes an outage. Any utility voltage below this value will trigger the generator to start (After the Start Delay has expired). This must be a whole number between 0 and 342." 77 | } 78 | ] 79 | }, 80 | { 81 | "onewordcommand" : "pickupvolts", 82 | "title" : "Pickup Volts", 83 | "command_sequence" : [ 84 | { 85 | "reg": "023b", 86 | "input_title": "Volts", 87 | "type": "int", 88 | "length": 2, 89 | "bounds_regex":"^(17[5-9]|1[89][0-9]|2[0-9]{2}|3[0-3][0-9]|34[0-2])$", 90 | "tooltip": "The utility voltage that denotes an outage is over.. This must be a whole number between 175 and 342." 91 | } 92 | ] 93 | } 94 | ] 95 | } -------------------------------------------------------------------------------- /data/commands/example_button.json: -------------------------------------------------------------------------------- 1 | { 2 | "buttons":[ 3 | { 4 | "information": "This is an example of how to add buttons to genmon", 5 | "onewordcommand" : "testexamplebutton", 6 | "title" : "Example Button", 7 | "command_sequence" : [ 8 | { 9 | "reg": "example_button.py", 10 | "reg_type": "script" 11 | } 12 | ] 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /data/commands/script/example_button.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------ 3 | # FILE: example_button.py 4 | # PURPOSE: 5 | # 6 | # AUTHOR: Jason G Yates 7 | # DATE: 10-Apr-2025 8 | # Free software. Use at your own risk. 9 | # MODIFICATIONS: 10 | # ------------------------------------------------------------ 11 | 12 | 13 | import os 14 | import sys 15 | 16 | # Adds higher directory to python modules path (e.g. ~/genmon) 17 | sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(sys.path[0])))) 18 | 19 | try: 20 | from genmonlib.mylog import SetupLogger 21 | except Exception as e1: 22 | print("\n\nThis is an example script and requires the directory structure of the genmon project to run.") 23 | print("Error: " + str(e1)) 24 | sys.exit(1) 25 | 26 | loglocation = "/var/log" 27 | scriptbasename = os.path.splitext(os.path.basename(__file__))[0] 28 | 29 | # ------------------------------------------------------------------------------- 30 | if __name__ == "__main__": 31 | 32 | 33 | log = SetupLogger("scriptbasename", os.path.join(loglocation, scriptbasename + ".log")) 34 | 35 | log.error("Running script " + scriptbasename) 36 | sys.exit(0) -------------------------------------------------------------------------------- /data/mib/README.md: -------------------------------------------------------------------------------- 1 | SNMP-MIB for GenMon. 2 | 3 | 4 | 5 | 6 | 7 | ABOUT: 8 | 9 | This MIB is provided to allow users and NMS applications to be able to query an 10 | SNMP-enabled GenMon installation using symbolic names rather than OIDs. 11 | 12 | The MIB in this directory assumes that the user is running GenMon with a 13 | default Enterprise ID of '58399'. 14 | 15 | If the user wishes to change the enterprise ID, the change has to be made in 16 | two locations: 17 | 18 | - The GenMon UI (under "Add-ons", under the SNMP Support window.) 19 | - The MIB file itself. (change line 10 after the 'enterprises' keyword ) 20 | 21 | Changing either location may cause the OIDs to not get mapped correctly and may 22 | cause unexpected errors in an SNMP-aware NMS. 23 | 24 | 25 | FILES: 26 | genmon.mib - The primary MIB file. 27 | 28 | 29 | GENERATOR SUPPORT: 30 | 31 | The MIB and underlying SNMP structure is controller agnostic however due to 32 | some OIDs only being used for specific controllers (or specific states of 33 | the generator), a blank response may be returned. 34 | 35 | Some OIDs will only return data if the generator is running, other OIDs will 36 | only return data for specific controllers (and again, only in certain states.) 37 | 38 | You can use snmptranslate to pull up a quick message about a particular OID. 39 | 40 | If the OID says: Then it will work on: 41 | (Evo/Nexus) Evolution or Nexus controllers. 42 | (h100) H100 controllers. 43 | (h100/PowerZone) H100 or PowerZone controllers. 44 | (PowerZone) Only PowerZone controllers. 45 | (Any controller) or (Generic) Any controller that works with GenMon. 46 | 47 | Be aware, some OIDs may not return data, even with the correct controller. 48 | A single phase H100 controller will not return data for GenMon-MIB::VoltageBC 49 | as that OID only populates for 3-phase generators. 50 | 51 | 52 | 53 | 54 | INSTALLATION: 55 | 56 | Installing these MIBs depends on which distribution or NMS application will be 57 | monitoring GenMon. For most cases, copying all .mib files in this directory 58 | to '/usr/share/snmp/mibs' is adequate, Other distributions may require the 59 | MIBs be copied to another directory. 60 | 61 | In some distributions, editing /etc/snmp/snmp.conf is necessary. Locate the 62 | "mibs" line (it may or may not be commented out) 63 | 64 | and add "ALL" to the end of it: 65 | 66 | (Before) > mibs : 67 | (after) > mibs ALL 68 | 69 | 70 | 71 | 72 | VERIFICATION: 73 | 74 | Verification of the MIBs can be performed using 'snmptranslate' as follows: 75 | 76 | > $ snmptranslate -Td GenMon-MIB::switchState 77 | 78 | which should return the following: 79 | 80 | > GenMon-MIB::switchState 81 | > switchState OBJECT-TYPE 82 | > -- FROM GenMon-MIB 83 | > SYNTAX OCTET STRING 84 | > MAX-ACCESS read-only 85 | > STATUS mandatory 86 | > DESCRIPTION "(All controllers) The current ready state of the generator based on control panel status. (Auto/Off/Manual)" 87 | > ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) genmon(58399) controllerID(0) status(0) engineData(0) 1 } 88 | 89 | 90 | If the above produces a result as above, you're all set. If it produces an 91 | error like the one below, check the MIB search path and ensure the MIBs in this 92 | directory are in one of the directories in the MIB search path. 93 | 94 | > $ snmptranslate -Td GenMon-MIB::switchState 95 | > MIB search path: /home/matt/.snmp/mibs:/usr/share/snmp/mibs:/usr/share/ \ 96 | > snmp/mibs/iana:/usr/share/snmp/mibs/ietf:/usr/share/mibs/site:/usr/share \ 97 | > /snmp/mibs:/usr/share/mibs/iana:/usr/share/mibs/ietf:/usr/share/mibs/netsnmp 98 | > Cannot find module (GenMon-MIB): At line 1 in (none) 99 | > GenMon-MIB::switchState: Unknown Object Identifier 100 | 101 | Finally, query the GenMon controller using snmpget: 102 | 103 | > $ snmpget -v1 -c public (hostname_or_IP_of_genmon) GenMon-MIB::switchState 104 | 105 | It should answer with the below (assuming your generator is in Auto mode): 106 | 107 | > GenMon-MIB::switchState = STRING: "Auto" 108 | 109 | From there, snmpwalk can be used to retrieve the OID data. 110 | 111 | > $ snmpwalk -v1 -c public (hostname_or_IP_of_genmon) . 112 | 113 | 114 | 115 | 116 | NAGIOS CONFIGURATION: 117 | 118 | Nagios contains a basic SNMP plugin called "check_snmp". While the full 119 | capabilities of check_snmp are beyond the scope of this document, a basic 120 | example is included below: 121 | 122 | > $ ./check_snmp -C public -H IP.ADDR.OF.GENMON -o GenMon-MIB::switchState \ 123 | -s \"Auto\" 124 | 125 | This command will return a CRITICAL status if the generator is not in "Auto" 126 | state. Using the -s parameter, you can set up Nagios to alert if the expected 127 | result string is not the result returned when polled. 128 | -------------------------------------------------------------------------------- /data/mib/genmon.json: -------------------------------------------------------------------------------- 1 | { 2 | "controller_type": "genmon", 3 | "comment": "This info is specific to genmon, not the controller. Monitor->Generator Monitor Stats", 4 | "snmp": [ 5 | { 6 | "oid":"0, 0, 1", 7 | "return_type": "str", 8 | "description":"MonitorHealth", 9 | "default":"Unknown", 10 | "keywords":["Monitor", "Monitor Health"] 11 | }, 12 | { 13 | "oid":"0, 0, 2", 14 | "return_type": "str", 15 | "description":"RunTime", 16 | "default":"Unknown", 17 | "keywords":["Monitor", "Run time"] 18 | }, 19 | { 20 | "oid":"0, 0, 3", 21 | "return_type": "str", 22 | "description":"PowerLogSize", 23 | "default":"", 24 | "keywords":["Monitor", "Power log file size"] 25 | }, 26 | { 27 | "oid":"0, 0, 4", 28 | "return_type": "str", 29 | "description":"Version", 30 | "default":"", 31 | "keywords":["Monitor", "Generator Monitor Version"] 32 | }, 33 | { 34 | "oid":"0, 1, 1", 35 | "return_type": "str", 36 | "description":"PacketCount", 37 | "default":"Unknown", 38 | "keywords":["Monitor/Communication Stats", "Packet Count"] 39 | }, 40 | { 41 | "oid":"0, 1, 2", 42 | "return_type": "str", 43 | "description":"CRCErrors", 44 | "default":"Unknown", 45 | "integer": true, 46 | "keywords":["Monitor/Communication Stats", "CRC Errors"] 47 | }, 48 | { 49 | "oid":"0, 1, 3", 50 | "return_type": "str", 51 | "description":"CRCPercent", 52 | "default":"Unknown", 53 | "keywords":["Monitor/Communication Stats", "CRC Percent Errors"] 54 | }, 55 | { 56 | "oid":"0, 1, 4", 57 | "return_type": "str", 58 | "description":"PacketTimeouts", 59 | "integer": true, 60 | "default":"Unknown", 61 | "keywords":["Monitor/Communication Stats", "Timeout Errors"] 62 | }, 63 | { 64 | "oid":"0, 1, 5", 65 | "return_type": "str", 66 | "description":"TimeoutPercent", 67 | "default":"Unknown", 68 | "keywords":["Monitor/Communication Stats", "Timeout Percent Errors"] 69 | }, 70 | { 71 | "oid":"0, 1, 6", 72 | "return_type": "str", 73 | "description":"ModbusErrors", 74 | "integer": true, 75 | "default":"Unknown", 76 | "keywords":["Monitor/Communication Stats", "Modbus Exceptions"] 77 | }, 78 | { 79 | "oid":"0, 1, 7", 80 | "return_type": "str", 81 | "description":"ValidationErrors", 82 | "integer": true, 83 | "default":"Unknown", 84 | "keywords":["Monitor/Communication Stats", "Validation Errors"] 85 | }, 86 | { 87 | "oid":"0, 1, 8", 88 | "return_type": "str", 89 | "description":"InvalidData", 90 | "integer": true, 91 | "default":"Unknown", 92 | "keywords":["Monitor/Communication Stats", "Invalid Data"] 93 | }, 94 | { 95 | "oid":"0, 1, 9", 96 | "return_type": "str", 97 | "description":"DiscardedBytes", 98 | "integer": true, 99 | "default":"Unknown", 100 | "keywords":["Monitor/Communication Stats", "Discarded Bytes"] 101 | }, 102 | { 103 | "oid":"0, 1, 10", 104 | "return_type": "str", 105 | "description":"CommRestarts", 106 | "integer": true, 107 | "default":"Unknown", 108 | "keywords":["Monitor/Communication Stats", "Comm Restarts"] 109 | }, 110 | { 111 | "oid":"0, 1, 11", 112 | "return_type": "str", 113 | "description":"PPS", 114 | "default":"Unknown", 115 | "keywords":["Monitor/Communication Stats", "Packets Per Second"] 116 | }, 117 | { 118 | "oid":"0, 1, 12", 119 | "return_type": "str", 120 | "description":"AvgTransTime", 121 | "default":"Unknown", 122 | "keywords":["Monitor/Communication Stats", "Average Transaction Time"] 123 | }, 124 | { 125 | "oid":"0, 2, 1", 126 | "return_type": "str", 127 | "description":"CPUTemp", 128 | "default":"Unknown", 129 | "keywords":["Monitor", "CPU Temperature"] 130 | }, 131 | { 132 | "oid":"0, 2, 2", 133 | "return_type": "str", 134 | "description":"PiModel", 135 | "default":"Unknown", 136 | "keywords":["Monitor", "Pi Model"] 137 | }, 138 | { 139 | "oid":"0, 2, 3", 140 | "return_type": "str", 141 | "description":"CPUFreqThrottling", 142 | "default":"Unknown", 143 | "keywords":["Monitor", "Pi CPU Frequency Throttling"] 144 | }, 145 | { 146 | "oid":"0, 2, 4", 147 | "return_type": "str", 148 | "description":"ARMFreqCap", 149 | "default":"Unknown", 150 | "keywords":["Monitor", "Pi ARM Frequency Cap"] 151 | }, 152 | { 153 | "oid":"0, 2, 5", 154 | "return_type": "str", 155 | "description":"ARMUnderVoltage", 156 | "default":"Unknown", 157 | "keywords":["Monitor", "Pi Undervoltage"] 158 | }, 159 | { 160 | "oid":"0, 2, 6", 161 | "return_type": "str", 162 | "description":"CPUUtil", 163 | "default":"Unknown", 164 | "keywords":["Monitor", "CPU Utilization"] 165 | }, 166 | { 167 | "oid":"0, 2, 7", 168 | "return_type": "str", 169 | "description":"OSName", 170 | "default":"Unknown", 171 | "keywords":["Monitor", "OS Name"] 172 | }, 173 | { 174 | "oid":"0, 2, 8", 175 | "return_type": "str", 176 | "description":"OSVersion", 177 | "default":"Unknown", 178 | "keywords":["Monitor", "OS Version"] 179 | }, 180 | { 181 | "oid":"0, 2, 9", 182 | "return_type": "str", 183 | "description":"SysUptime", 184 | "default":"Unknown", 185 | "keywords":["Monitor", "System Uptime"] 186 | }, 187 | { 188 | "oid":"0, 2, 10", 189 | "return_type": "str", 190 | "description":"NetInterface", 191 | "default":"Unknown", 192 | "keywords":["Monitor", "Network Interface Used"] 193 | } 194 | ] 195 | } -------------------------------------------------------------------------------- /feature_requests.md: -------------------------------------------------------------------------------- 1 | # Feature Request List 2 | - [SNMP v2 and v3 for gensnmp add-on](https://github.com/jgyates/genmon/issues/705) @w-u-2-o 3 | - [Add options for custom alarm descriptions for H-100 and PowerZone](https://github.com/jgyates/genmon/issues/660) @j45p3r2 4 | - [Dark Mode for web interface](https://github.com/jgyates/genmon/issues/602) @danodemano 5 | - [Add ATS test using power reading](https://github.com/jgyates/genmon/issues/593) @skipfire 6 | - [Discovery for Home Assistant](https://github.com/jgyates/genmon/issues/590) @dave-parsons 7 | - [Make Service Journal entries sortable and filterable](https://github.com/jgyates/genmon/issues/584) @nickdot 8 | - [Option to remember 2FA for 30 days](https://github.com/jgyates/genmon/issues/565) @danodemano 9 | - [Connecting Genmon to Homebridge (and ultimately Homekit)](https://github.com/jgyates/genmon/issues/552) @muddycharles68 10 | - [add support for a Cummins Quiet Connect generator](https://github.com/jgyates/genmon/issues/553) @derekatkins 11 | - [TX Industrial Switch support](https://github.com/jgyates/genmon/issues/463) @unsword01 12 | - [Unified web interface for running multiple instances of generator monitor](https://github.com/jgyates/genmon/issues/260) - @KUBAllen 13 | - [Translate to other languages](https://github.com/jgyates/genmon/issues/239) - @JMVS 14 | - [Start & Transfer after x dropouts in a period of time](https://github.com/jgyates/genmon/issues/353) - @JMVS 15 | - [Status Screen enhancements Utility Voltage Trend and weather](https://github.com/jgyates/genmon/issues/439) - @gzebrick 16 | - [View past power output in 1 hour chunks](https://github.com/jgyates/genmon/issues) - @skipfire 17 | - [A HTTP and SNMP watchdog would be really a nice addition](https://github.com/jgyates/genmon/issues/735) - @acato 18 | - [Add user defined levels to low fuel notifications](https://github.com/jgyates/genmon/issues/818) @rwskinner 19 | - [Add option to restore backup settings](https://github.com/jgyates/genmon/issues/829) @dmperl 20 | - [Hardware keys (FIDO2) for 2fa](https://github.com/jgyates/genmon/issues/841) @danodemano 21 | - [Add the ability to save pictures in the service journal](https://github.com/jgyates/genmon/issues/896) @northportio 22 | - [Ecobee thermostat messaging](https://github.com/jgyates/genmon/issues/921) @wtnh 23 | - [Kiosk mode](https://github.com/jgyates/genmon/issues/970) @mstackler 24 | - Add the ability to report the temperature of mopeka tank sensors in the UI and SNMP/MQTT 25 | - Add the ability to set the name of external tank 26 | - [Add reading watchdog in gentankutil](https://github.com/jgyates/genmon/issues/1018) 27 | - [Keep alive for Silk broswers](https://github.com/jgyates/genmon/discussions/1059) 28 | - [Save Gauge Layout](https://github.com/jgyates/genmon/discussions/1078) 29 | - [Add on to monitor key values and alert if out of range](https://github.com/jgyates/genmon/discussions/1089) 30 | - [Manual Start and Transfer but stop after x minutes](https://github.com/jgyates/genmon/discussions/1174) @jkh62 31 | - [Add device specific messaging to pushover](https://github.com/jgyates/genmon/issues/1246) @noumenon272 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /genmonlib/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------------------------- 3 | # FILE: __init__.py 4 | # PURPOSE: genmonlib support 5 | # 6 | # AUTHOR: Jason G Yates 7 | # DATE: 19-Apr-2018 8 | # 9 | # MODIFICATIONS: 10 | # ------------------------------------------------------------------------------- 11 | -------------------------------------------------------------------------------- /genmonlib/myclient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------------------------- 3 | # FILE: myclient.py 4 | # PURPOSE: 5 | # 6 | # AUTHOR: Jason G Yates 7 | # DATE: 5-Apr-2017 8 | # MODIFICATIONS: 9 | # ------------------------------------------------------------------------------- 10 | import os 11 | import socket 12 | import sys 13 | import threading 14 | import time 15 | 16 | from genmonlib.mycommon import MyCommon 17 | from genmonlib.mylog import SetupLogger 18 | from genmonlib.program_defaults import ProgramDefaults 19 | 20 | 21 | # ---------- ClientInterface::init--- ------------------------------------------ 22 | class ClientInterface(MyCommon): 23 | def __init__( 24 | self, 25 | host=ProgramDefaults.LocalHost, 26 | port=ProgramDefaults.ServerPort, 27 | log=None, 28 | loglocation=ProgramDefaults.LogPath, 29 | ): 30 | super(ClientInterface, self).__init__() 31 | if log != None: 32 | self.log = log 33 | else: 34 | # log errors in this module to a file 35 | self.log = SetupLogger("client", os.path.join(loglocation, "myclient.log")) 36 | 37 | self.console = SetupLogger("client_console", log_file="", stream=True) 38 | 39 | self.AccessLock = threading.RLock() 40 | self.EndOfMessage = "EndOfMessage" 41 | self.rxdatasize = 2098152 # max json string size plus 1000 42 | self.host = host 43 | self.port = port 44 | self.max_reties = 10 45 | self.Connect() 46 | 47 | # ---------- ClientInterface::Connect -------------------------------------- 48 | def Connect(self): 49 | 50 | retries = 0 51 | while True: 52 | 53 | try: 54 | # create an INET, STREAMing socket 55 | self.Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 56 | 57 | # now connect to the server on our port 58 | self.Socket.connect((self.host, self.port)) 59 | sRetData, data = self.Receive( 60 | noeom=True 61 | ) # Get initial status before commands are sent 62 | self.console.info(data) 63 | return 64 | except Exception as e1: 65 | retries += 1 66 | if retries >= self.max_reties: 67 | self.LogErrorLine("Error: Connect : " + str(e1)) 68 | self.console.error("Genmon not loaded.") 69 | sys.exit(1) 70 | else: 71 | time.sleep(1) 72 | continue 73 | 74 | # ---------- ClientInterface::SendCommand ---------------------------------- 75 | def SendCommand(self, cmd): 76 | 77 | try: 78 | self.Socket.sendall(cmd.encode("utf-8")) 79 | except Exception as e1: 80 | self.LogErrorLine("Error: TX: " + str(e1)) 81 | self.Close() 82 | self.Connect() 83 | 84 | # ---------- ClientInterface::Receive -------------------------------------- 85 | def Receive(self, noeom=False): 86 | 87 | with self.AccessLock: 88 | RetStatus = True 89 | try: 90 | bytedata = self.Socket.recv(self.rxdatasize) 91 | data = bytedata.decode("utf-8") 92 | if len(data): 93 | if not self.CheckForStarupMessage(data) or not noeom: 94 | while not self.EndOfMessage in data: 95 | morebytes = self.Socket.recv(self.rxdatasize) 96 | more = morebytes.decode("utf-8") 97 | if len(more): 98 | if self.CheckForStarupMessage(more): 99 | data = "" 100 | RetStatus = False 101 | break 102 | data += more 103 | 104 | if data.endswith(self.EndOfMessage): 105 | data = data[: -len(self.EndOfMessage)] 106 | RetStatus = True 107 | else: 108 | self.Connect() 109 | return False, data 110 | except Exception as e1: 111 | self.LogErrorLine("Error: RX:" + str(e1)) 112 | self.Close() 113 | self.Connect() 114 | RetStatus = False 115 | data = "Retry" 116 | 117 | return RetStatus, data 118 | 119 | # ---------- ClientInterface::CheckForStarupMessage ------------------------ 120 | def CheckForStarupMessage(self, data): 121 | 122 | # check for initial status response from monitor 123 | if ( 124 | data.startswith("OK") 125 | or data.startswith("CRITICAL:") 126 | or data.startswith("WARNING:") 127 | ): 128 | return True 129 | else: 130 | return False 131 | 132 | # ---------- ClientInterface::Close ---------------------------------------- 133 | def Close(self): 134 | self.Socket.close() 135 | 136 | # ---------- ClientInterface::ProcessMonitorCommand ------------------------ 137 | def ProcessMonitorCommand(self, cmd): 138 | 139 | data = "" 140 | try: 141 | with self.AccessLock: 142 | RetStatus = False 143 | while RetStatus == False: 144 | self.SendCommand(cmd) 145 | RetStatus, data = self.Receive() 146 | except Exception as e1: 147 | self.LogErrorLine("Error in ProcessMonitorCommand:" + str(e1)) 148 | return data 149 | -------------------------------------------------------------------------------- /genmonlib/mylog.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------- 2 | # PURPOSE: setup logging 3 | # 4 | # AUTHOR: Jason G Yates 5 | # DATE: 03-Dec-2016 6 | # 7 | # MODIFICATIONS: 8 | # ------------------------------------------------------------------------------- 9 | import logging 10 | import logging.handlers 11 | 12 | 13 | # ---------- SetupLogger -------------------------------------------------------- 14 | def SetupLogger(logger_name, log_file, level=logging.INFO, stream=False): 15 | 16 | logger = logging.getLogger(logger_name) 17 | 18 | # remove existing logg handlers 19 | for handler in logger.handlers[:]: # make a copy of the list 20 | logger.removeHandler(handler) 21 | 22 | logger.setLevel(level) 23 | 24 | if log_file != "": 25 | formatter = logging.Formatter("%(asctime)s : %(message)s") 26 | rotate = logging.handlers.RotatingFileHandler( 27 | log_file, mode="a", maxBytes=50000, backupCount=5 28 | ) 29 | rotate.setFormatter(formatter) 30 | logger.addHandler(rotate) 31 | 32 | if stream: # print to screen also? 33 | LOG_FORMAT = "%(message)s" 34 | streamHandler = logging.StreamHandler() 35 | formatter = logging.Formatter(LOG_FORMAT) 36 | streamHandler.setFormatter(formatter) 37 | # Dont format stream log messages 38 | logger.addHandler(streamHandler) 39 | 40 | return logging.getLogger(logger_name) 41 | -------------------------------------------------------------------------------- /genmonlib/mymsgqueue.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------------------------- 3 | # FILE: mymsgqueue.py 4 | # PURPOSE: message queue with retry support 5 | # 6 | # AUTHOR: Jason G Yates 7 | # DATE: 16-Feb-2022 8 | # 9 | # MODIFICATIONS: 10 | # ------------------------------------------------------------------------------- 11 | 12 | import datetime 13 | import threading 14 | import time 15 | 16 | from genmonlib.mysupport import MySupport 17 | from genmonlib.mythread import MyThread 18 | 19 | 20 | # ------------ MyMsgQueue class ------------------------------------------------- 21 | class MyMsgQueue(MySupport): 22 | # ------------ MyMsgQueue::init---------------------------------------------- 23 | def __init__(self, config=None, log=None, debug=False,callback=None, minimum_wait_between_messages = 0): 24 | super(MyMsgQueue, self).__init__() 25 | self.log = log 26 | self.config = config 27 | self.callback = callback 28 | self.MessageQueue = [] 29 | 30 | self.QueueLock = threading.RLock() 31 | 32 | self.max_retry_time = 600 # 10 min 33 | self.default_wait = 120 # 2 min 34 | self.minimum_wait_between_messages = minimum_wait_between_messages 35 | self.last_message_sent_time = None 36 | 37 | self.debug = debug 38 | 39 | if self.config != None: 40 | try: 41 | self.max_retry_time = self.config.ReadValue( 42 | "max_retry_time", return_type=int, default=600 43 | ) 44 | self.default_wait = self.config.ReadValue( 45 | "default_wait", return_type=int, default=120 46 | ) 47 | self.minimum_wait_between_messages = self.config.ReadValue( 48 | "minimum_wait_between_messages", return_type=int, default=minimum_wait_between_messages 49 | ) 50 | self.debug = self.config.ReadValue( 51 | "debug", return_type=bool, default=False 52 | ) 53 | self.LogDebug("Min Wait Between Messages: " + str(self.minimum_wait_between_messages)) 54 | except Exception as e1: 55 | self.LogErrorLine( 56 | "Error in MyMsgQueue:init, error reading config: " + str(e1) 57 | ) 58 | if not self.callback == None: 59 | self.Threads["QueueWorker"] = MyThread( 60 | self.QueueWorker, Name="QueueWorker", start=False 61 | ) 62 | self.Threads["QueueWorker"].Start() 63 | 64 | # ------------ MyMsgQueue::QueueWorker--------------------------------------- 65 | def QueueWorker(self): 66 | 67 | # once SendMessage is called messages are queued and then sent from this thread 68 | time.sleep(0.1) 69 | while True: 70 | 71 | while self.MessageQueue != []: 72 | messageError = False 73 | try: 74 | message_time = datetime.datetime.now() 75 | if self.last_message_sent_time != None and ((message_time - self.last_message_sent_time).total_seconds() < self.minimum_wait_between_messages): 76 | if self.WaitForExit("QueueWorker", self.minimum_wait_between_messages): 77 | return 78 | continue 79 | with self.QueueLock: 80 | MessageItems = self.MessageQueue.pop() 81 | if len(MessageItems[1]): 82 | ret_val = self.callback(MessageItems[0], **MessageItems[1]) 83 | else: 84 | ret_val = self.callback(MessageItems[0]) 85 | if not (ret_val): 86 | self.LogError("Error sending message in QueueWorker, callback failed, retrying") 87 | messageError = True 88 | except Exception as e1: 89 | self.LogErrorLine("Error in QueueWorker, retrying (2): " + str(e1)) 90 | messageError = True 91 | 92 | try: 93 | if messageError: 94 | # check max retry timeout 95 | retry_duration = datetime.datetime.now() - MessageItems[2] 96 | if retry_duration.total_seconds() <= self.max_retry_time: 97 | with self.QueueLock: 98 | # put the message back at the end of the queue 99 | self.MessageQueue.insert( 100 | len(self.MessageQueue), MessageItems 101 | ) 102 | # sleep for 2 min and try again 103 | if self.WaitForExit("QueueWorker", self.default_wait): 104 | return 105 | else: 106 | self.LogDebug("Message retry expired: " + MessageItems[0]) 107 | else: 108 | # message was sent 109 | self.LogDebug("Message Sent") 110 | self.last_message_sent_time = message_time 111 | except Exception as e1: 112 | self.LogErrorLine( 113 | "Error in QueueWorker requeue, retrying (3): " + str(e1) 114 | ) 115 | 116 | if self.WaitForExit("QueueWorker", 2): 117 | return 118 | 119 | # ------------ MyMsgQueue::SendMessage--------------------------------------- 120 | def SendMessage(self, message, **kwargs): 121 | try: 122 | if self.callback != None: 123 | with self.QueueLock: 124 | MessageItems = [] 125 | MessageItems.append(message) 126 | MessageItems.append(kwargs) 127 | MessageItems.append(datetime.datetime.now()) 128 | self.MessageQueue.insert(0, MessageItems) 129 | except Exception as e1: 130 | self.LogErrorLine("Error in MyMsgQueue:SendMessage: " + str(e1)) 131 | 132 | # ------------ MyMsgQueue::Close--------------------------------------------- 133 | def Close(self): 134 | 135 | try: 136 | if not self.callback == None: 137 | self.KillThread("QueueWorker") 138 | except Exception as e1: 139 | self.LogErrorLine("Error in MyMsgQueue:Close: " + str(e1)) 140 | -------------------------------------------------------------------------------- /genmonlib/mythread.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------- 2 | # PURPOSE: manage threads 3 | # 4 | # AUTHOR: Jason G Yates 5 | # DATE: 04-Mar-2017 6 | # 7 | # MODIFICATIONS: 8 | # ------------------------------------------------------------------------------- 9 | 10 | import threading 11 | 12 | 13 | # ---------- MyThread----------------------------------------------------------- 14 | class MyThread: 15 | # Thread class with a stop() method. The thread itself has to check 16 | # regularly for the stopped() condition. 17 | 18 | # ---------- MyThread::MyThread--------------------------------------------- 19 | def __init__(self, ThreadFunction, Name=None, start=True): 20 | self.StopEvent = threading.Event() 21 | self.ThreadObj = threading.Thread(target=ThreadFunction, name=Name) 22 | self.ThreadObj.daemon = True 23 | if start: 24 | self.Start() 25 | 26 | # ---------- MyThread::Stop------------------------------------------------- 27 | def GetThreadObject(self): 28 | return self.ThreadObj 29 | 30 | # ---------- MyThread::Start------------------------------------------------ 31 | def Start(self, timeout=None): 32 | self.ThreadObj.start() # start thread 33 | 34 | # ---------- MyThread::Wait------------------------------------------------- 35 | def Wait(self, timeout=None): 36 | return self.StopEvent.wait(timeout) 37 | 38 | # ---------- MyThread::Stop------------------------------------------------- 39 | def Stop(self): 40 | self.StopEvent.set() 41 | 42 | # ---------- MyThread::StopSignaled----------------------------------------- 43 | def StopSignaled(self): 44 | return self.StopEvent.is_set() 45 | 46 | # ---------- MyThread::IsAlive---------------------------------------------- 47 | def IsAlive(self): 48 | return self.ThreadObj.is_alive() 49 | 50 | # ---------- MyThread::Name------------------------------------------------- 51 | def Name(self): 52 | return self.ThreadObj.name 53 | 54 | # ---------- MyThread::Name------------------------------------------------- 55 | def WaitForThreadToEnd(self, Timeout=None): 56 | return self.ThreadObj.join(Timeout) 57 | -------------------------------------------------------------------------------- /genmonlib/myvoipms.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #------------------------------------------------------------------------------- 3 | # FILE: voipms.py 4 | # PURPOSE: Send text message using voip.ms service 5 | # 6 | # AUTHOR: Jason G Yates 7 | # DATE: 06-05-2021 8 | # 9 | # MODIFICATIONS: 10 | # 11 | # USAGE: 12 | # 13 | #------------------------------------------------------------------------------- 14 | 15 | import os, sys 16 | 17 | from genmonlib.mysupport import MySupport 18 | 19 | 20 | #------------ MyVoipMs class ------------------------------------------------- 21 | class MyVoipMs(MySupport): 22 | 23 | #------------ MyVoipMs::init------------------------------------------------ 24 | def __init__(self, log = None, console = None, username = None, password = None, did = None, debug = False): 25 | self.log = log 26 | self.console = console 27 | self.username = username 28 | self.password = password 29 | self.did = did 30 | self.debug = debug 31 | 32 | self.debug = False 33 | try: 34 | from voipms import VoipMs 35 | # https://github.com/4doom4/python-voipms 36 | self.client = VoipMs(self.username, self.password) 37 | 38 | # IP addresses allowed to send SMS 39 | ipaddresses = self.client.general.get.ip() 40 | # WAN IP address of this computer 41 | wanipaddress = self.GetWANIp() 42 | 43 | self.LogDebug("WanIP: " + str(wanipaddress) + " Client IP: " + str(ipaddresses)) 44 | # Allowed ip must match our WAN IP 45 | if wanipaddress != ipaddresses['ip']: 46 | self.LogError("Warning WanIP and VoipMS IP addresses do not match: " + str(wanipaddress) + ": " + ipaddresses['ip']) 47 | 48 | except Exception as e1: 49 | self.LogErrorLine("Error in MyVoipMs:init: " + str(e1)) 50 | sys.exit(1) 51 | #------------ MyVoipMs::SendSMS----------------------------------------------- 52 | def SendSMS(self, destination, message): 53 | try: 54 | status = self.client.dids.send.sms(self.did, destination, message) 55 | if status["status"] != 'success': 56 | self.LogError("Error sending SMS: " + str(status)) 57 | return False 58 | return True 59 | except Exception as e1: 60 | self.LogErrorLine("Error in MyVoipMs:SendSMS: " + str(e1)) 61 | return False 62 | -------------------------------------------------------------------------------- /genmonlib/program_defaults.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # ------------------------------------------------------------------------------- 3 | # FILE: program_defaults.py 4 | # PURPOSE: default values 5 | # 6 | # AUTHOR: Jason G Yates 7 | # DATE: 10-May-2019 8 | # 9 | # MODIFICATIONS: 10 | # ------------------------------------------------------------------------------- 11 | 12 | 13 | # ------------ ProgramDefaults class --------------------------------------------- 14 | class ProgramDefaults(object): 15 | ConfPath = "/etc/genmon/" 16 | LogPath = "/var/log/" 17 | ServerPort = 9082 18 | LocalHost = "127.0.0.1" 19 | GENMON_VERSION = "V1.19.06" 20 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | configparser 3 | pyserial 4 | crcmod 5 | pyowm==2.10.0 6 | pytz 7 | pyopenssl==24.1.0 8 | twilio 9 | chump 10 | paho-mqtt==1.6.1 11 | smbus 12 | pysnmp==5.1.0 13 | ldap3 14 | pyasn1==0.4.8 15 | pyotp 16 | smbus 17 | psutil 18 | spidev 19 | bleson @ git+https://github.com/TheCellule/python-bleson 20 | fluids 21 | voipms==0.2.5 22 | RPi.GPIO -------------------------------------------------------------------------------- /startgenmon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # bash script to start, stop or restart genmon. the scrip calls genloader.py 3 | # with the needed command line parameters and can use python 2.7 or 3.x to call 4 | # genloader.py 5 | #------------------------------------------------------------------------------- 6 | PARAMS="" 7 | genmondir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | pythoncommand="python3" 9 | pipcommand="pip3" 10 | config_path="" 11 | usepython3=true 12 | found_action=false 13 | managedpackages=false 14 | 15 | 16 | #------------------------------------------------------------------------------- 17 | function env_activate() { 18 | 19 | if [ "$managedpackages" = true ] ; then 20 | source $genmondir/genenv/bin/activate 21 | fi 22 | } 23 | #------------------------------------------------------------------------------- 24 | function env_deactivate() { 25 | if [ "$managedpackages" = true ] ; then 26 | deactivate 27 | fi 28 | } 29 | #------------------------------------------------------------------------------- 30 | function checkmanagedpackages() { 31 | 32 | # /usr/lib/python3.11/EXTERNALLY-MANAGED 33 | pythonmajor=$($pythoncommand -c 'import sys; print(sys.version_info.major)') 34 | pythonminor=$($pythoncommand -c 'import sys; print(sys.version_info.minor)') 35 | managedfile="/usr/lib/python$pythonmajor.$pythonminor/EXTERNALLY-MANAGED" 36 | 37 | if [ -f $managedfile ]; then 38 | pythoncommand="$genmondir/genenv/bin/python" 39 | managedpackages=true 40 | echo "using binary: $pythoncommand" 41 | fi 42 | } 43 | #------------------------------------------------------------------------------- 44 | function setuppython3() { 45 | 46 | if [ $# -eq 0 ]; then 47 | usepython3=false 48 | elif [ $1 == "3" ]; then 49 | usepython3=true 50 | elif [ $1 == "2" ]; then 51 | usepython3=false 52 | else 53 | usepython3=false 54 | fi 55 | 56 | if [ "$usepython3" = true ] ; then 57 | echo 'Using Python 3.x...' 58 | pipcommand="pip3" 59 | pythoncommand="python3" 60 | else 61 | echo 'Using Python 2.x...' 62 | pipcommand="pip2" 63 | pythoncommand="python2" 64 | fi 65 | } 66 | 67 | #------------------------------------------------------------------------------- 68 | function printhelp(){ 69 | echo "usage: " 70 | echo " " 71 | echo "./startgenmon.sh start|stop|restart|hardstop" 72 | echo "" 73 | echo "valid options:" 74 | echo " -h display help" 75 | echo " -c path of config files" 76 | echo " -p Specifiy 2 or 3 for python version. 2 is default" 77 | echo "" 78 | } 79 | 80 | #------------------------------------------------------------------------------- 81 | # main 82 | while (( "$#" )); do 83 | case "$1" in 84 | -p) 85 | setuppython3 $2 86 | shift 2 87 | ;; 88 | -c) 89 | if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then 90 | config_path="-c $2" 91 | shift 2 92 | else 93 | echo "Error: Argument for $1 is missing" >&2 94 | exit 1 95 | fi 96 | ;; 97 | -h) 98 | printhelp 99 | exit 0 100 | ;; 101 | -*|--*=) # unsupported flags 102 | echo "Error: Unsupported flag $1" >&2 103 | exit 1 104 | ;; 105 | *) # preserve positional arguments 106 | PARAMS="$PARAMS $1" 107 | shift 108 | ;; 109 | esac 110 | done 111 | checkmanagedpackages 112 | for val in $PARAMS; do 113 | case "$val" in 114 | start) 115 | echo "Starting genmon python scripts" 116 | env_activate 117 | found_action=true 118 | sudo $pythoncommand "$genmondir/genloader.py" -s $config_path 119 | env_deactivate 120 | ;; 121 | stop) 122 | found_action=true 123 | env_activate 124 | echo "Stopping genmon python scripts" 125 | sudo $pythoncommand "$genmondir/genloader.py" -x $config_path 126 | env_deactivate 127 | ;; 128 | hardstop) 129 | found_action=true 130 | env_activate 131 | echo "Hard Stopping genmon python scripts" 132 | sudo $pythoncommand "$genmondir/genloader.py" -z $config_path 133 | env_deactivate 134 | ;; 135 | restart) 136 | found_action=true 137 | env_activate 138 | echo "Restarting genmon python scripts" 139 | sudo $pythoncommand "$genmondir/genloader.py" -r $config_path 140 | env_deactivate 141 | ;; 142 | *) 143 | # 144 | echo "Additional command found: " $val 145 | ;; 146 | esac 147 | done 148 | 149 | if [ "$found_action" = false ] ; then 150 | echo "Invalid command. Valid commands are start, stop, restart or hardstop." 151 | fi 152 | 153 | exit 0 154 | -------------------------------------------------------------------------------- /static/closure-compiler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | import os.path 5 | import re 6 | import shutil 7 | import urllib 8 | import zipfile 9 | from time import sleep 10 | 11 | import requests 12 | 13 | 14 | def compress(compiler, in_files, out_file, in_type="js"): 15 | 16 | if in_type == "js": 17 | print( 18 | 'java -jar %s --js "%s" --js_output_file "%s"' 19 | % (compiler, '" --js "'.join(in_files), out_file) 20 | ) 21 | os.system( 22 | 'java -jar %s --js "%s" --js_output_file "%s"' 23 | % (compiler, '" --js "'.join(in_files), out_file) 24 | ) 25 | 26 | if in_type == "css": 27 | print( 28 | 'java -jar %s --allow-unrecognized-functions --allow-unrecognized-properties --output-file "%s" "%s"' 29 | % (compiler, out_file, '" "'.join(in_files)) 30 | ) 31 | os.system( 32 | 'java -jar %s --allow-unrecognized-functions --allow-unrecognized-properties --output-file "%s" "%s"' 33 | % (compiler, out_file, '" "'.join(in_files)) 34 | ) 35 | 36 | 37 | MINIFY_SCRIPTS = [ 38 | "js/jquery-3.7.0.min.js", 39 | "js/jquery-ui.min.js", 40 | "js/jquery.ui.touch-punch.min.js", 41 | "js/tooltipster.bundle.js", 42 | "js/vex.combined.min.js", 43 | "js/gauge.min.js", 44 | "js/jquery.jqplot.min.js", 45 | "js/jqplot.dateAxisRenderer.js", 46 | "js/printThis.js", 47 | "js/moment.min.js", 48 | "js/lc_switch.genmon.js", 49 | "js/selectize.min.js", 50 | "js/packery.pkgd.min.js", 51 | "js/jquery.idealforms.genmon.js", 52 | "js/jquery.CalendarHeatmap.genmon.js", 53 | "js/jquery.timepicker.min.js", 54 | "js/jquery.qrcode.min.js", 55 | "genmon.js", 56 | ] 57 | NON_MINIFY_SCRIPTS = [] 58 | SCRIPTS_OUT = "libraries.min.js" 59 | 60 | STYLESHEETS = [ 61 | "css/jquery-ui.css", 62 | "genmon.css", 63 | "css/jquery.idealforms.css", 64 | "css/lc_switch.css", 65 | "css/selectize.default.css", 66 | "css/vex.css", 67 | "css/jquery.CalendarHeatmap.css", 68 | "css/jquery.jqplot.min.css", 69 | "css/tooltipster.bundle.min.css", 70 | "css/vex-theme-os.css", 71 | "css/jquery.timepicker.min.css", 72 | ] 73 | STYLESHEETS_OUT = "libraries.min.css" 74 | 75 | 76 | def main(): 77 | 78 | CLOSURE_COMPILER = "closure-compiler-v20200719.jar" 79 | CLOSURE_STYLESHEET = "closure-stylesheets.jar" 80 | 81 | print("Downlaod Compilers...") 82 | 83 | r = requests.get( 84 | "https://repo1.maven.org/maven2/com/google/javascript/closure-compiler/v20200719/closure-compiler-v20200719.jar", 85 | allow_redirects=True, 86 | ) # to get content after redirection 87 | with open(CLOSURE_COMPILER, "wb") as f: 88 | f.write(r.content) 89 | # r = requests.get("https://dl.google.com/closure-compiler/compiler-latest.zip", allow_redirects=True) # to get content after redirection 90 | # with open("compiler-latest.zip", 'wb') as f: 91 | # f.write(r.content) 92 | # zip_ref = zipfile.ZipFile("compiler-latest.zip", 'r') 93 | # filenames = zip_ref.namelist() 94 | # CLOSURE_COMPILER = list(filter(lambda x: re.search(r'.jar', x), filenames))[0] 95 | # zip_ref.extract(CLOSURE_COMPILER, '.') 96 | # zip_ref.close() 97 | # os.remove("compiler-latest.zip") 98 | 99 | print("Downloaded: " + CLOSURE_COMPILER) 100 | 101 | r = requests.get( 102 | "https://github.com/google/closure-stylesheets/releases/download/v1.5.0/closure-stylesheets.jar", 103 | allow_redirects=True, 104 | ) # to get content after redirection 105 | with open(CLOSURE_STYLESHEET, "wb") as f: 106 | f.write(r.content) 107 | print("Downloaded: " + CLOSURE_STYLESHEET) 108 | 109 | print("Compressing JavaScript...") 110 | compress(CLOSURE_COMPILER, MINIFY_SCRIPTS, SCRIPTS_OUT, "js") 111 | 112 | # temp = open(SCRIPTS_OUT, 'a') 113 | # for f in NON_MINIFY_SCRIPTS: 114 | # fh = open(f) 115 | # data = fh.read() + '\n' 116 | # fh.close() 117 | # 118 | # temp.write(data) 119 | # 120 | # print ' + %s' % f 121 | # temp.close() 122 | 123 | print("Compressing JavaScript Completed...") 124 | sleep(5) 125 | 126 | print("Compressing CSS...") 127 | compress(CLOSURE_STYLESHEET, STYLESHEETS, STYLESHEETS_OUT, "css") 128 | print("Compressing CSS Completed...") 129 | 130 | os.remove(CLOSURE_COMPILER) 131 | os.remove(CLOSURE_STYLESHEET) 132 | print("Clean-Up completed...") 133 | 134 | 135 | if __name__ == "__main__": 136 | main() 137 | -------------------------------------------------------------------------------- /static/css/jquery.CalendarHeatmap.css: -------------------------------------------------------------------------------- 1 | /* 2 | * calendarheatmap - v0.0.3 3 | * A simple Calendar Heatmap for jQuery. 4 | * https://github.com/SeBassTian23/CalendarHeatmap 5 | * 6 | * Made by Sebastian Kuhlgert 7 | * Under MIT License 8 | */ 9 | .ch { 10 | display: table !important; 11 | clear: both; 12 | } 13 | .ch-month, 14 | .ch-week-labels { 15 | font-size: 0; 16 | display: inline-block; 17 | white-space: normal; 18 | margin: 0 4px; 19 | } 20 | .ch-week, 21 | .ch-day-labels { 22 | display: inline-block; 23 | width: 11px; 24 | box-sizing: content-box; 25 | } 26 | .ch-day-labels { 27 | width: inherit; 28 | } 29 | .ch-month-label { 30 | text-align: center; 31 | font-size: 12px; 32 | margin-top: 10px; 33 | margin-bottom: 10px; 34 | } 35 | .ch-day-label { 36 | text-align: center; 37 | font-size: 10px; 38 | display: block; 39 | margin: 0; 40 | line-height: 11px; 41 | box-sizing: content-box; 42 | } 43 | .ch-day { 44 | display: inline-block; 45 | width: 9px; 46 | height: 9px; 47 | border: 1px solid #f3f6f8; 48 | background-color: #f1f1f1; 49 | margin: 0; 50 | box-sizing: content-box; 51 | } 52 | .ch-day.is-outside-month, 53 | .ch-lvl.is-outside-month, 54 | .ch-day.is-outside-month:hover, 55 | .ch-lvl.is-outside-month:hover { 56 | background-color: transparent; 57 | border-color: transparent; 58 | } 59 | .ch-day.lvl-0, 60 | .ch-lvl.lvl-0 { 61 | background-color: #c8d7e1; 62 | } 63 | .ch-day.is-after-today, 64 | .ch-lvl.is-after-today { 65 | background-color: #d9e3ea; 66 | } 67 | .ch-day.lvl-1, 68 | .ch-lvl.lvl-1 { 69 | background-color: #a6c96a; 70 | } 71 | .ch-day.lvl-2, 72 | .ch-lvl.lvl-2 { 73 | background-color: #5cb85c; 74 | } 75 | .ch-day.lvl-3, 76 | .ch-lvl.lvl-3 { 77 | background-color: #009e47; 78 | } 79 | .ch-day.lvl-4, 80 | .ch-lvl.lvl-4 { 81 | background-color: #00753a; 82 | } 83 | .ch-day:hover, 84 | .ch-lvl:hover { 85 | border-color: #89a6ba; 86 | } 87 | .ch-legend { 88 | padding-top: 10px; 89 | text-align: right; 90 | } 91 | .ch-legend-left { 92 | text-align: left !important; 93 | } 94 | .ch-legend-center { 95 | text-align: center !important; 96 | } 97 | .ch-legend:after { 98 | content: "."; 99 | display: block; 100 | height: 0; 101 | width: 0; 102 | clear: both; 103 | visibility: hidden; 104 | } 105 | .ch-lvls { 106 | display: inline-block; 107 | margin: 0; 108 | list-style-type: none; 109 | padding: 2px 9px 0 5px; 110 | } 111 | .ch-lvl { 112 | width: 10px; 113 | height: 10px; 114 | float: left; 115 | margin-left: 3px; 116 | } 117 | .blue-1 { 118 | background-color: #ffffcc !important; 119 | } 120 | .earth-1 { 121 | background-color: #f4ec15 !important; 122 | } 123 | .electric-1 { 124 | background-color: #f9d824 !important; 125 | } 126 | .viridis-1 { 127 | background-color: #dde218 !important; 128 | } 129 | .picknick-1 { 130 | background-color: #dd2a91 !important; 131 | } 132 | .green-1 { 133 | background-color: #d1be5a !important; 134 | } 135 | .teal-1 { 136 | background-color: #becfb6 !important; 137 | } 138 | .red-1 { 139 | background-color: #deb7af !important; 140 | } 141 | .blue-2 { 142 | background-color: #41b6c4 !important; 143 | } 144 | .earth-2 { 145 | background-color: #86bf76 !important; 146 | } 147 | .electric-2 { 148 | background-color: #f38647 !important; 149 | } 150 | .viridis-2 { 151 | background-color: #42bd70 !important; 152 | } 153 | .picknick-2 { 154 | background-color: #b14dec !important; 155 | } 156 | .green-2 { 157 | background-color: #5f900b !important; 158 | } 159 | .teal-2 { 160 | background-color: #7db28f !important; 161 | } 162 | .red-2 { 163 | background-color: #cf8371 !important; 164 | } 165 | .blue-3 { 166 | background-color: #0868ac !important; 167 | } 168 | .earth-3 { 169 | background-color: #117bd7 !important; 170 | } 171 | .electric-3 { 172 | background-color: #8e0ca3 !important; 173 | } 174 | .viridis-3 { 175 | background-color: #355c8c !important; 176 | } 177 | .picknick-3 { 178 | background-color: #2e8ebf !important; 179 | } 180 | .green-3 { 181 | background-color: #39811b !important; 182 | } 183 | .teal-3 { 184 | background-color: #107d79 !important; 185 | } 186 | .red-3 { 187 | background-color: #b63b25 !important; 188 | } 189 | .blue-4 { 190 | background-color: #253494 !important; 191 | } 192 | .earth-4 { 193 | background-color: #363299 !important; 194 | } 195 | .electric-4 { 196 | background-color: #2e0495 !important; 197 | } 198 | .viridis-4 { 199 | background-color: #471164 !important; 200 | } 201 | .picknick-4 { 202 | background-color: #139863 !important; 203 | } 204 | .green-4 { 205 | background-color: #0d562c !important; 206 | } 207 | .teal-4 { 208 | background-color: #1c475d !important; 209 | } 210 | .red-4 { 211 | background-color: #90131c !important; 212 | } 213 | .genmon-1 { 214 | background-color: #009900 !important; 215 | } 216 | .genmon-2 { 217 | background-color: #ff9900 !important; 218 | } 219 | .genmon-3 { 220 | background-color: #cc0000 !important; 221 | } 222 | .genmon-4 { 223 | background-color: #333333 !important; 224 | } 225 | -------------------------------------------------------------------------------- /static/css/jquery.jqplot.min.css: -------------------------------------------------------------------------------- 1 | .jqplot-xaxis,.jqplot-xaxis-label{margin-top:10px}.jqplot-x2axis,.jqplot-x2axis-label{margin-bottom:10px}.jqplot-target{position:relative;color:#666;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:1em}.jqplot-axis{font-size:.75em}.jqplot-yaxis{margin-right:10px}.jqplot-y2axis,.jqplot-y3axis,.jqplot-y4axis,.jqplot-y5axis,.jqplot-y6axis,.jqplot-y7axis,.jqplot-y8axis,.jqplot-y9axis,.jqplot-yMidAxis{margin-left:10px;margin-right:10px}.jqplot-axis-tick,.jqplot-x2axis-tick,.jqplot-xaxis-tick,.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick,.jqplot-yMidAxis-tick,.jqplot-yaxis-tick{position:absolute;white-space:pre}.jqplot-xaxis-tick{top:0;left:15px;vertical-align:top}.jqplot-x2axis-tick{bottom:0;left:15px;vertical-align:bottom}.jqplot-yaxis-tick{right:0;top:15px;text-align:right}.jqplot-yaxis-tick.jqplot-breakTick{right:-20px;margin-right:0;padding:1px 5px;z-index:2;font-size:1.5em}.jqplot-x2axis-label,.jqplot-xaxis-label,.jqplot-yMidAxis-label,.jqplot-yaxis-label{font-size:11pt;position:absolute}.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick{left:0;top:15px;text-align:left}.jqplot-yMidAxis-tick{text-align:center;white-space:nowrap}.jqplot-yaxis-label{margin-right:10px}.jqplot-y2axis-label,.jqplot-y3axis-label,.jqplot-y4axis-label,.jqplot-y5axis-label,.jqplot-y6axis-label,.jqplot-y7axis-label,.jqplot-y8axis-label,.jqplot-y9axis-label{font-size:11pt;margin-left:10px;position:absolute}.jqplot-meterGauge-tick{font-size:.75em;color:#999}.jqplot-meterGauge-label{font-size:1em;color:#999}table.jqplot-table-legend{margin:12px}table.jqplot-cursor-legend,table.jqplot-table-legend{background-color:rgba(255,255,255,.6);border:1px solid #ccc;position:absolute;font-size:.75em}td.jqplot-table-legend{vertical-align:middle}td.jqplot-seriesToggle:active,td.jqplot-seriesToggle:hover{cursor:pointer}.jqplot-table-legend .jqplot-series-hidden{text-decoration:line-through}div.jqplot-table-legend-swatch-outline{border:1px solid #ccc;padding:1px}div.jqplot-table-legend-swatch{width:0;height:0;border-width:5px 6px;border-style:solid}.jqplot-title{top:0;left:0;padding-bottom:.5em;font-size:1.2em}table.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em}.jqplot-canvasOverlay-tooltip,.jqplot-cursor-tooltip,.jqplot-highlighter-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,.5);padding:1px}.jqplot-point-label{font-size:.75em;z-index:2}td.jqplot-cursor-legend-swatch{vertical-align:middle;text-align:center}div.jqplot-cursor-legend-swatch{width:1.2em;height:.7em}.jqplot-error{text-align:center}.jqplot-error-message{position:relative;top:46%;display:inline-block}div.jqplot-bubble-label{font-size:.8em;padding-left:2px;padding-right:2px;color:rgb(20%,20%,20%)}div.jqplot-bubble-label.jqplot-bubble-label-highlight{background:rgba(90%,90%,90%,.7)}div.jqplot-noData-container{text-align:center;background-color:rgba(96%,96%,96%,.3)} -------------------------------------------------------------------------------- /static/css/jquery.timepicker.min.css: -------------------------------------------------------------------------------- 1 | .ui-timepicker-wrapper{overflow-y:auto;max-height:150px;width:6.5em;background:#fff;border:1px solid #ddd;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);outline:0;z-index:10052;margin:0}.ui-timepicker-wrapper.ui-timepicker-with-duration{width:13em}.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30,.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60{width:11em}.ui-timepicker-list{margin:0;padding:0;list-style:none}.ui-timepicker-duration{margin-left:5px;color:#888}.ui-timepicker-list:hover .ui-timepicker-duration{color:#888}.ui-timepicker-list li{padding:3px 0 3px 5px;cursor:pointer;white-space:nowrap;color:#000;list-style:none;margin:0}.ui-timepicker-list:hover .ui-timepicker-selected{background:#fff;color:#000}li.ui-timepicker-selected,.ui-timepicker-list li:hover,.ui-timepicker-list .ui-timepicker-selected:hover{background:#1980EC;color:#fff}li.ui-timepicker-selected .ui-timepicker-duration,.ui-timepicker-list li:hover .ui-timepicker-duration{color:#ccc}.ui-timepicker-list li.ui-timepicker-disabled,.ui-timepicker-list li.ui-timepicker-disabled:hover,.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled{color:#888;cursor:default}.ui-timepicker-list li.ui-timepicker-disabled:hover,.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled{background:#f2f2f2} -------------------------------------------------------------------------------- /static/css/lc_switch.css: -------------------------------------------------------------------------------- 1 | .lcs_wrap { 2 | display: inline-block; 3 | direction: ltr; 4 | height: 28px; 5 | vertical-align: middle; 6 | } 7 | .lcs_wrap input { 8 | display: none; 9 | } 10 | 11 | .lcs_switch { 12 | display: inline-block; 13 | position: relative; 14 | width: 73px; 15 | height: 28px; 16 | border-radius: 30px; 17 | background: #ddd; 18 | overflow: hidden; 19 | cursor: pointer; 20 | 21 | -webkit-transition: all .2s ease-in-out; 22 | -ms-transition: all .2s ease-in-out; 23 | transition: all .2s ease-in-out; 24 | } 25 | .lcs_cursor { 26 | display: inline-block; 27 | position: absolute; 28 | top: 3px; 29 | width: 22px; 30 | height: 22px; 31 | border-radius: 100%; 32 | background: #fff; 33 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2), 0 3px 4px 0 rgba(0, 0, 0, 0.1); 34 | z-index: 10; 35 | 36 | -webkit-transition: all .2s linear; 37 | -ms-transition: all .2s linear; 38 | transition: all .2s linear; 39 | } 40 | .lcs_label { 41 | font-family: "Trebuchet MS", Helvetica, sans-serif; 42 | font-size: 12px; 43 | letter-spacing: 1px; 44 | line-height: 18px; 45 | color: #fff; 46 | font-weight: bold; 47 | position: absolute; 48 | width: 33px; 49 | top: 5px; 50 | overflow: hidden; 51 | text-align: center; 52 | opacity: 0; 53 | 54 | -webkit-transition: all .2s ease-in-out .1s; 55 | -ms-transition: all .2s ease-in-out .1s; 56 | transition: all .2s ease-in-out .1s; 57 | } 58 | .lcs_label.lcs_label_on { 59 | left: -70px; 60 | z-index: 6; 61 | } 62 | .lcs_label.lcs_label_off { 63 | right: -70px; 64 | z-index: 5; 65 | } 66 | 67 | 68 | /* on */ 69 | .lcs_switch.lcs_on { 70 | /* background: #4CAF50; */ 71 | background: -webkit-linear-gradient(#439547, #4CAF50); 72 | /* @alternate */ background: linear-gradient(#439547, #4CAF50); 73 | text-shadow: 0 0 8px rgba(0, 0, 0, 0.5); 74 | border-radius: 50px; 75 | box-shadow: inset 2px 2px 5px rgba(0, 0, 0, 0.4); 76 | } 77 | .lcs_switch.lcs_on .lcs_cursor { 78 | left: 48px; 79 | } 80 | .lcs_switch.lcs_on .lcs_label_on { 81 | left: 10px; 82 | opacity: 1; 83 | } 84 | 85 | 86 | /* off */ 87 | .lcs_switch.lcs_off { 88 | background: #b2b2b2; 89 | box-shadow: 0px 0px 2px #a4a4a4 inset; 90 | border-radius: 50px; 91 | } 92 | .lcs_switch.lcs_off .lcs_cursor { 93 | left: 3px; 94 | } 95 | .lcs_switch.lcs_off .lcs_label_off { 96 | right: 10px; 97 | opacity: 1; 98 | } 99 | 100 | 101 | /* disabled */ 102 | .lcs_switch.lcs_disabled { 103 | opacity: 0.65; 104 | filter: alpha(opacity=65); 105 | cursor: default; 106 | } 107 | -------------------------------------------------------------------------------- /static/css/print.css: -------------------------------------------------------------------------------- 1 | /* style sheet for "A4" printing */ 2 | @media print and (width: 21cm) and (height: 29.7cm) { 3 | @page { 4 | margin: 2cm; 5 | } 6 | } 7 | /* style sheet for "letter" printing */ 8 | @media print and (width: 8.5in) and (height: 11in) { 9 | @page { 10 | margin: .8in; 11 | } 12 | } 13 | 14 | h1 { 15 | font-size: 36px; 16 | font-weight: bold; 17 | font-family: Arial; 18 | } 19 | 20 | h2 { 21 | font-size: 28px; 22 | font-weight: bold; 23 | font-family: Arial; 24 | } 25 | 26 | .printRegisterTD { 27 | border:5px solid white; 28 | background-color: #AAAAAA; 29 | vertical-align:top; 30 | padding:5px; 31 | background-clip: padding-box; /* this has been added in CSS3 */ 32 | border-radius: 10px; 33 | font-weight: bold; 34 | font-family: Arial; 35 | } 36 | 37 | .printRegisterTD table { 38 | border:2px solid #AAAAAA; 39 | height:100%; 40 | } 41 | 42 | .printRegisterTDtitle { 43 | font-weight: bold; 44 | font-family: Arial; 45 | border-bottom: 1px solid #444444; 46 | font-size:20px; 47 | height:50px; 48 | } 49 | 50 | .printRegisterTDsubtitle { 51 | border-bottom: 1px solid #444444; 52 | font-weight: bold; 53 | font-family: Arial; 54 | font-size:16px; 55 | } 56 | 57 | .printRegisterTDvalMedium { 58 | font-weight: bold; 59 | font-family: Arial; 60 | font-size:18px; 61 | } 62 | 63 | .printRegisterTDvalSmall { 64 | font-weight: bold; 65 | font-family: Arial; 66 | font-size:16px; 67 | } 68 | 69 | .pagebreak { 70 | page-break-before: always; 71 | } 72 | -------------------------------------------------------------------------------- /static/css/tooltipster.bundle.min.css: -------------------------------------------------------------------------------- 1 | .tooltipster-fall,.tooltipster-grow.tooltipster-show{-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1);-moz-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-ms-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-o-transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-base{display:flex;pointer-events:none;position:absolute}.tooltipster-box{flex:1 1 auto}.tooltipster-content{box-sizing:border-box;max-height:100%;max-width:100%;overflow:auto;font-size:12px}.tooltipster-ruler{bottom:0;left:0;overflow:hidden;position:fixed;right:0;top:0;visibility:hidden}.tooltipster-fade{opacity:0;-webkit-transition-property:opacity;-moz-transition-property:opacity;-o-transition-property:opacity;-ms-transition-property:opacity;transition-property:opacity}.tooltipster-fade.tooltipster-show{opacity:1}.tooltipster-grow{-webkit-transform:scale(0,0);-moz-transform:scale(0,0);-o-transform:scale(0,0);-ms-transform:scale(0,0);transform:scale(0,0);-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform;-webkit-backface-visibility:hidden}.tooltipster-grow.tooltipster-show{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-o-transform:scale(1,1);-ms-transform:scale(1,1);transform:scale(1,1);-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-swing{opacity:0;-webkit-transform:rotateZ(4deg);-moz-transform:rotateZ(4deg);-o-transform:rotateZ(4deg);-ms-transform:rotateZ(4deg);transform:rotateZ(4deg);-webkit-transition-property:-webkit-transform,opacity;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform}.tooltipster-swing.tooltipster-show{opacity:1;-webkit-transform:rotateZ(0);-moz-transform:rotateZ(0);-o-transform:rotateZ(0);-ms-transform:rotateZ(0);transform:rotateZ(0);-webkit-transition-timing-function:cubic-bezier(.23,.635,.495,1);/* @alternate */ -webkit-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);-moz-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);-ms-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);-o-transition-timing-function:cubic-bezier(.23,.635,.495,2.4);transition-timing-function:cubic-bezier(.23,.635,.495,2.4)}.tooltipster-fall{-webkit-transition-property:top;-moz-transition-property:top;-o-transition-property:top;-ms-transition-property:top;transition-property:top;-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-fall.tooltipster-initial{top:0!important}.tooltipster-fall.tooltipster-dying{-webkit-transition-property:all;-moz-transition-property:all;-o-transition-property:all;-ms-transition-property:all;transition-property:all;top:0!important;opacity:0}.tooltipster-slide{-webkit-transition-property:left;-moz-transition-property:left;-o-transition-property:left;-ms-transition-property:left;transition-property:left;-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1);/* @alternate */-webkit-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-moz-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-ms-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);-o-transition-timing-function:cubic-bezier(.175,.885,.32,1.15);transition-timing-function:cubic-bezier(.175,.885,.32,1.15)}.tooltipster-slide.tooltipster-initial{left:-40px!important}.tooltipster-slide.tooltipster-dying{-webkit-transition-property:all;-moz-transition-property:all;-o-transition-property:all;-ms-transition-property:all;transition-property:all;left:0!important;opacity:0}@keyframes tooltipster-fading{0%{opacity:0}100%{opacity:1}}.tooltipster-update-fade{animation:tooltipster-fading .4s}@keyframes tooltipster-rotating{25%{transform:rotate(-2deg)}75%{transform:rotate(2deg)}100%{transform:rotate(0)}}.tooltipster-update-rotate{animation:tooltipster-rotating .6s}@keyframes tooltipster-scaling{50%{transform:scale(1.1)}100%{transform:scale(1)}}.tooltipster-update-scale{animation:tooltipster-scaling .6s}.tooltipster-sidetip .tooltipster-box{background:#565656;border:2px solid #000;border-radius:4px}.tooltipster-sidetip.tooltipster-bottom .tooltipster-box{margin-top:8px}.tooltipster-sidetip.tooltipster-left .tooltipster-box{margin-right:8px}.tooltipster-sidetip.tooltipster-right .tooltipster-box{margin-left:8px}.tooltipster-sidetip.tooltipster-top .tooltipster-box{margin-bottom:8px}.tooltipster-sidetip .tooltipster-content{color:#fff;line-height:18px;padding:6px 14px}.tooltipster-sidetip .tooltipster-arrow{overflow:hidden;position:absolute}.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow{height:10px;margin-left:-10px;top:0;width:20px}.tooltipster-sidetip.tooltipster-left .tooltipster-arrow{height:20px;margin-top:-10px;right:0;top:0;width:10px}.tooltipster-sidetip.tooltipster-right .tooltipster-arrow{height:20px;margin-top:-10px;left:0;top:0;width:10px}.tooltipster-sidetip.tooltipster-top .tooltipster-arrow{bottom:0;height:10px;margin-left:-10px;width:20px}.tooltipster-sidetip .tooltipster-arrow-background,.tooltipster-sidetip .tooltipster-arrow-border{height:0;position:absolute;width:0}.tooltipster-sidetip .tooltipster-arrow-background{border:10px solid transparent}.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-background{border-bottom-color:#565656;left:0;top:3px}.tooltipster-sidetip.tooltipster-left .tooltipster-arrow-background{border-left-color:#565656;left:-3px;top:0}.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-background{border-right-color:#565656;left:3px;top:0}.tooltipster-sidetip.tooltipster-top .tooltipster-arrow-background{border-top-color:#565656;left:0;top:-3px}.tooltipster-sidetip .tooltipster-arrow-border{border:10px solid transparent;left:0;top:0}.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-border{border-bottom-color:#000}.tooltipster-sidetip.tooltipster-left .tooltipster-arrow-border{border-left-color:#000}.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-border{border-right-color:#000}.tooltipster-sidetip.tooltipster-top .tooltipster-arrow-border{border-top-color:#000}.tooltipster-sidetip .tooltipster-arrow-uncropped{position:relative}.tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-uncropped{top:-10px}.tooltipster-sidetip.tooltipster-right .tooltipster-arrow-uncropped{left:-10px} -------------------------------------------------------------------------------- /static/css/vex.css: -------------------------------------------------------------------------------- 1 | @-webkit-keyframes vex-fadein { 2 | 0% { 3 | opacity: 0; } 4 | 100% { 5 | opacity: 1; } } 6 | 7 | @keyframes vex-fadein { 8 | 0% { 9 | opacity: 0; } 10 | 100% { 11 | opacity: 1; } } 12 | 13 | @-webkit-keyframes vex-fadeout { 14 | 0% { 15 | opacity: 1; } 16 | 100% { 17 | opacity: 0; } } 18 | 19 | @keyframes vex-fadeout { 20 | 0% { 21 | opacity: 1; } 22 | 100% { 23 | opacity: 0; } } 24 | 25 | @-webkit-keyframes vex-rotation { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); } 29 | 100% { 30 | -webkit-transform: rotate(359deg); 31 | transform: rotate(359deg); } } 32 | 33 | @keyframes vex-rotation { 34 | 0% { 35 | -webkit-transform: rotate(0deg); 36 | transform: rotate(0deg); } 37 | 100% { 38 | -webkit-transform: rotate(359deg); 39 | transform: rotate(359deg); } } 40 | 41 | .vex, .vex *, .vex *:before, .vex *:after { 42 | -moz-box-sizing: border-box; 43 | box-sizing: border-box; } 44 | 45 | .vex { 46 | position: fixed; 47 | overflow: auto; 48 | -webkit-overflow-scrolling: touch; 49 | z-index: 1111; 50 | top: 0; 51 | right: 0; 52 | bottom: 0; 53 | left: 0; } 54 | 55 | .vex-scrollbar-measure { 56 | position: absolute; 57 | top: -9999px; 58 | width: 50px; 59 | height: 50px; 60 | overflow: scroll; } 61 | 62 | .vex-overlay { 63 | -webkit-animation: vex-fadein .5s; 64 | animation: vex-fadein .5s; 65 | position: fixed; 66 | z-index: 1111; 67 | background: rgba(0, 0, 0, 0.4); 68 | top: 0; 69 | right: 0; 70 | bottom: 0; 71 | left: 0; } 72 | 73 | .vex-overlay.vex-closing { 74 | -webkit-animation: vex-fadeout .5s forwards; 75 | animation: vex-fadeout .5s forwards; } 76 | 77 | .vex-content { 78 | -webkit-animation: vex-fadein .5s; 79 | animation: vex-fadein .5s; 80 | background: #fff; } 81 | 82 | .vex.vex-closing .vex-content { 83 | -webkit-animation: vex-fadeout .5s forwards; 84 | animation: vex-fadeout .5s forwards; } 85 | 86 | .vex-close:before { 87 | font-family: Arial, sans-serif; 88 | content: "\00D7"; } 89 | 90 | .vex-dialog-form { 91 | margin: 0; } 92 | 93 | .vex-dialog-button { 94 | text-rendering: optimizeLegibility; 95 | -webkit-appearance: none; 96 | -moz-appearance: none; 97 | appearance: none; 98 | cursor: pointer; 99 | -webkit-tap-highlight-color: transparent; } 100 | 101 | .vex-loading-spinner { 102 | -webkit-animation: vex-rotation .7s linear infinite; 103 | animation: vex-rotation .7s linear infinite; 104 | box-shadow: 0 0 1em rgba(0, 0, 0, 0.1); 105 | position: fixed; 106 | z-index: 1112; 107 | margin: auto; 108 | top: 0; 109 | right: 0; 110 | bottom: 0; 111 | left: 0; 112 | height: 2em; 113 | width: 2em; 114 | background: #fff; } 115 | 116 | body.vex-open { 117 | overflow: hidden; } 118 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/favicon.ico -------------------------------------------------------------------------------- /static/images/GenmonLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/GenmonLogo.png -------------------------------------------------------------------------------- /static/images/addons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/addons.png -------------------------------------------------------------------------------- /static/images/raw/Genmon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/Genmon.png -------------------------------------------------------------------------------- /static/images/raw/Genmon_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/Genmon_small.png -------------------------------------------------------------------------------- /static/images/raw/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/about.png -------------------------------------------------------------------------------- /static/images/raw/addon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/addon.png -------------------------------------------------------------------------------- /static/images/raw/alert_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/alert_large.png -------------------------------------------------------------------------------- /static/images/raw/alert_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/alert_small.png -------------------------------------------------------------------------------- /static/images/raw/dd_arrow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/dd_arrow.gif -------------------------------------------------------------------------------- /static/images/raw/fuel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/fuel.png -------------------------------------------------------------------------------- /static/images/raw/journal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/journal.png -------------------------------------------------------------------------------- /static/images/raw/log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/log.png -------------------------------------------------------------------------------- /static/images/raw/maintenance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/maintenance.png -------------------------------------------------------------------------------- /static/images/raw/monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/monitor.png -------------------------------------------------------------------------------- /static/images/raw/notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/notifications.png -------------------------------------------------------------------------------- /static/images/raw/outage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/outage.png -------------------------------------------------------------------------------- /static/images/raw/print10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/print10.png -------------------------------------------------------------------------------- /static/images/raw/print24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/print24.png -------------------------------------------------------------------------------- /static/images/raw/print60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/print60.png -------------------------------------------------------------------------------- /static/images/raw/registers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/registers.png -------------------------------------------------------------------------------- /static/images/raw/remove_bin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/remove_bin.png -------------------------------------------------------------------------------- /static/images/raw/selftest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/selftest.png -------------------------------------------------------------------------------- /static/images/raw/selftest_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/selftest_small.png -------------------------------------------------------------------------------- /static/images/raw/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/settings.png -------------------------------------------------------------------------------- /static/images/raw/status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/status.png -------------------------------------------------------------------------------- /static/images/raw/temp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/temp1.png -------------------------------------------------------------------------------- /static/images/raw/temp2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/temp2.png -------------------------------------------------------------------------------- /static/images/raw/temp3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/temp3.png -------------------------------------------------------------------------------- /static/images/raw/temp4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/temp4.png -------------------------------------------------------------------------------- /static/images/raw/title-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/title-bg.gif -------------------------------------------------------------------------------- /static/images/raw/validation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/validation.png -------------------------------------------------------------------------------- /static/images/raw/validation_ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/validation_ok.png -------------------------------------------------------------------------------- /static/images/raw/validation_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/validation_text.png -------------------------------------------------------------------------------- /static/images/raw/wifi1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/wifi1.png -------------------------------------------------------------------------------- /static/images/raw/wifi2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/wifi2.png -------------------------------------------------------------------------------- /static/images/raw/wifi3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/wifi3.png -------------------------------------------------------------------------------- /static/images/raw/wifi4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/raw/wifi4.png -------------------------------------------------------------------------------- /static/images/sprites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/sprites.png -------------------------------------------------------------------------------- /static/images/transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/transparent.png -------------------------------------------------------------------------------- /static/images/ui-bg_flat_75_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/ui-bg_flat_75_ffffff_40x100.png -------------------------------------------------------------------------------- /static/images/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /static/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /static/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /static/images/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /static/images/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /static/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /static/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Generator Monitor 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 27 | 28 | 29 |
23 |
24 |

25 |
26 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /static/index_lowbandwith.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Generator Monitor 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | 40 | 41 | 42 | 47 | 48 | 49 |
43 |
44 |

45 |
46 |
50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /static/index_verbose.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Generator Monitor 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 | 48 | 49 | 50 | 55 | 56 | 57 |
51 |
52 |

53 |
54 |
58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /static/internal.css: -------------------------------------------------------------------------------- 1 | /* BEGIN RESET*/ 2 | html, body, div, span, applet, object, iframe, 3 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 4 | a, abbr, acronym, address, big, cite, code, 5 | del, dfn, em, img, ins, kbd, q, s, samp, 6 | strike, strong, sub, sup, tt, var, 7 | b, u, i, center, 8 | dl, dt, dd, ol, ul, li, 9 | fieldset, form, label, legend, 10 | table, caption, tbody, tfoot, thead, tr, th, td, 11 | article, aside, canvas, details, embed, 12 | figure, figcaption, footer, header, hgroup, 13 | menu, nav, output, ruby, section, summary, 14 | time, mark, audio, video { 15 | margin: 0; 16 | padding: 0; 17 | border: 0; 18 | font-size: 100%; 19 | font: inherit; 20 | vertical-align: baseline; 21 | } 22 | /* HTML5 display-role reset for older browsers */ 23 | article, aside, details, figcaption, figure, 24 | footer, header, hgroup, menu, nav, section { 25 | display: block; 26 | } 27 | body { 28 | line-height: 1; 29 | } 30 | ol, ul { 31 | list-style: none; 32 | } 33 | blockquote, q { 34 | quotes: none; 35 | } 36 | blockquote:before, blockquote:after, 37 | q:before, q:after { 38 | content: ''; 39 | content: none; 40 | } 41 | table { 42 | border-collapse: collapse; 43 | border-spacing: 0; 44 | } 45 | input { 46 | font-size: 100%; 47 | font: inherit; 48 | vertical-align: baseline; 49 | } 50 | /* END RESET*/ 51 | body { 52 | font-size: 18px; 53 | font-weight: bold; 54 | font-family: Arial; 55 | background-color: white; 56 | margin: 0; 57 | } 58 | header { 59 | background-color: #f1f1f1; 60 | clear: left; 61 | text-align: center; 62 | font-size: 20px 63 | } 64 | footer { 65 | background-color: #f1f1f1; 66 | clear: left; 67 | text-align: center; 68 | font-size: 15px 69 | } 70 | a { 71 | font-style: italic; 72 | } 73 | h1 { 74 | font-style: italic; 75 | font-size: 20px 76 | } 77 | p { 78 | font-size: 18px; 79 | } 80 | /* */ 81 | 82 | 83 | 84 | /* Hack for firefox*/ 85 | :-moz-tree-row(hover),#days, #hours, #minutes, #quietmode, #daysep, #timesep, #modesep { 86 | padding: 0px; 87 | } 88 | -------------------------------------------------------------------------------- /static/internal.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Generator Registers 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

17 | 18 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /static/js/jquery.ui.touch-punch.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery UI Touch Punch 0.2.3 3 | * 4 | * Copyright 2011–2014, Dave Furfero 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * 7 | * Depends: 8 | * jquery.ui.widget.js 9 | * jquery.ui.mouse.js 10 | */ 11 | !function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery); -------------------------------------------------------------------------------- /static/js/keep.silk.alive.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Keep Silk Open 3 | * https://gitlab.com/DaGammla/keep-silk-open 4 | * 5 | * Released under the MIT license 6 | * https://gitlab.com/DaGammla/keep-silk-open/-/blob/main/LICENSE 7 | * 8 | * 2022 by DaGammla 9 | */ 10 | 11 | (() => { 12 | const userAgent = navigator.userAgent.toLowerCase() 13 | const alwaysUse = typeof AlwaysUseSilk != "undefined" && !!AlwaysUseSilk 14 | 15 | if (userAgent.includes("silk") || alwaysUse){ 16 | 17 | const visualMode = typeof SilkVisualMode != "undefined" && !!SilkVisualMode 18 | 19 | let source = document.currentScript.getAttribute("src") 20 | const lastDivider = source.lastIndexOf("/") 21 | source = source.slice(0, lastDivider + 1) + "media/media.mp3" 22 | 23 | const nowQuery = () => `?q=${Date.now()}` 24 | 25 | const audio = document.createElement("audio") 26 | audio.controls = visualMode 27 | audio.src = source + nowQuery() 28 | audio.muted = true 29 | audio.autoplay = true 30 | document.body.appendChild(audio) 31 | 32 | const listenEvents = ["keydown", "pointerdown", "click"] 33 | 34 | const addAllListeners = (listener) => { 35 | listenEvents.forEach(ev => { 36 | document.addEventListener(ev, listener) 37 | }); 38 | } 39 | 40 | const removeAllListeners = (listener) => { 41 | listenEvents.forEach(ev => { 42 | document.removeEventListener(ev, listener) 43 | }); 44 | } 45 | 46 | const reload = () => { 47 | audio.src = source + nowQuery() 48 | audio.currentTime = 0 49 | audio.play() 50 | } 51 | 52 | audio.onended = reload 53 | 54 | const startMedia = () => { 55 | reload() 56 | audio.muted = false 57 | } 58 | 59 | audio.onplaying = () => removeAllListeners(startMedia) 60 | 61 | addAllListeners(startMedia) 62 | } 63 | })() -------------------------------------------------------------------------------- /static/js/lc_switch.genmon.js: -------------------------------------------------------------------------------- 1 | /** 2 | * lc_switch.js 3 | * Version: 1.0 4 | * Author: LCweb - Luca Montanari 5 | * Website: http://www.lcweb.it 6 | * Licensed under the MIT license 7 | */ 8 | 9 | (function($){ 10 | if(typeof($.fn.lc_switch) != 'undefined') {return false;} // prevent dmultiple scripts inits 11 | 12 | $.fn.lc_switch = function(on_text, off_text) { 13 | 14 | // destruct 15 | $.fn.lcs_destroy = function() { 16 | 17 | $(this).each(function() { 18 | var $wrap = $(this).parents('.lcs_wrap'); 19 | 20 | $wrap.children().not('input').remove(); 21 | $(this).unwrap(); 22 | }); 23 | 24 | return true; 25 | }; 26 | 27 | 28 | // set to ON 29 | $.fn.lcs_on = function() { 30 | 31 | $(this).each(function() { 32 | var $wrap = $(this).parents('.lcs_wrap'); 33 | var $input = $wrap.find('input'); 34 | 35 | if(typeof($.fn.prop) == 'function') { 36 | $wrap.find('input').prop('checked', true); 37 | } else { 38 | $wrap.find('input').attr('checked', true); 39 | } 40 | 41 | eval($wrap.find('input').attr("data-callback")); 42 | 43 | $wrap.find('input').trigger('lcs-on'); 44 | $wrap.find('input').trigger('lcs-statuschange'); 45 | $wrap.find('.lcs_switch').removeClass('lcs_off').addClass('lcs_on'); 46 | 47 | // if radio - disable other ones 48 | if( $wrap.find('.lcs_switch').hasClass('lcs_radio_switch') ) { 49 | var f_name = $input.attr('name'); 50 | $wrap.parents('form').find('input[name='+f_name+']').not($input).lcs_off(); 51 | } 52 | }); 53 | 54 | return true; 55 | }; 56 | 57 | 58 | // set to OFF 59 | $.fn.lcs_off = function() { 60 | 61 | $(this).each(function() { 62 | var $wrap = $(this).parents('.lcs_wrap'); 63 | 64 | if(typeof($.fn.prop) == 'function') { 65 | $wrap.find('input').prop('checked', false); 66 | } else { 67 | $wrap.find('input').attr('checked', false); 68 | } 69 | eval($wrap.find('input').attr("data-callback")); 70 | 71 | $wrap.find('input').trigger('lcs-off'); 72 | $wrap.find('input').trigger('lcs-statuschange'); 73 | $wrap.find('.lcs_switch').removeClass('lcs_on').addClass('lcs_off'); 74 | }); 75 | 76 | return true; 77 | }; 78 | 79 | 80 | // construct 81 | return this.each(function(){ 82 | 83 | // check against double init 84 | if( !$(this).parent().hasClass('lcs_wrap') ) { 85 | 86 | // default texts 87 | var ckd_on_txt = (typeof(on_text) == 'undefined') ? 'ON' : on_text; 88 | var ckd_off_txt = (typeof(off_text) == 'undefined') ? 'OFF' : off_text; 89 | 90 | // labels structure 91 | var on_label = (ckd_on_txt) ? '
'+ ckd_on_txt +'
' : ''; 92 | var off_label = (ckd_off_txt) ? '
'+ ckd_off_txt +'
' : ''; 93 | 94 | 95 | // default states 96 | var disabled = ($(this).is(':disabled')) ? true: false; 97 | var active = ($(this).is(':checked')) ? true : false; 98 | 99 | var status_classes = ''; 100 | status_classes += (active) ? ' lcs_on' : ' lcs_off'; 101 | if(disabled) {status_classes += ' lcs_disabled';} 102 | 103 | 104 | // wrap and append 105 | var structure = 106 | '
' + 107 | '
' + 108 | on_label + off_label + 109 | '
'; 110 | 111 | if( $(this).is(':input') && ($(this).attr('type') == 'checkbox' || $(this).attr('type') == 'radio') ) { 112 | 113 | $(this).wrap('
'); 114 | $(this).parent().append(structure); 115 | 116 | $(this).parent().find('.lcs_switch').addClass('lcs_'+ $(this).attr('type') +'_switch'); 117 | } 118 | } 119 | }); 120 | }; 121 | 122 | 123 | 124 | // handlers 125 | $(document).ready(function() { 126 | 127 | // on click 128 | $(document).delegate('.lcs_switch:not(.lcs_disabled)', 'click tap', function(e) { 129 | 130 | if( $(this).hasClass('lcs_on') ) { 131 | if( !$(this).hasClass('lcs_radio_switch') ) { // not for radio 132 | $(this).lcs_off(); 133 | } 134 | } else { 135 | $(this).lcs_on(); 136 | } 137 | }); 138 | 139 | 140 | // on checkbox status change 141 | $(document).delegate('.lcs_wrap input', 'change', function() { 142 | 143 | if( $(this).is(':checked') ) { 144 | $(this).lcs_on(); 145 | } else { 146 | $(this).lcs_off(); 147 | } 148 | }); 149 | 150 | }); 151 | 152 | })(jQuery); 153 | -------------------------------------------------------------------------------- /static/media/media.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgyates/genmon/801dab543053384947f4d31bdf94675eaa8ca650/static/media/media.mp3 -------------------------------------------------------------------------------- /templates/command_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Unknown Command {{ command }}!

6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /templates/locked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Genmon login is locked due to exceeding the maximum login attempts. Please try again in {{ time }} seconds.

6 | 7 | 8 | 9 | --------------------------------------------------------------------------------