@frangoteam/fuxa-min 1.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +41 -0
- package/_images/Pipes/P1.svg +39 -0
- package/_images/Tanks/Fl.svg +7 -0
- package/api/alarms/index.js +132 -0
- package/api/auth/index.js +71 -0
- package/api/command/index.js +187 -0
- package/api/daq/index.js +79 -0
- package/api/diagnose/index.js +163 -0
- package/api/index.js +181 -0
- package/api/jwt-helper.js +106 -0
- package/api/plugins/index.js +109 -0
- package/api/projects/index.js +229 -0
- package/api/resources/index.js +118 -0
- package/api/scripts/index.js +82 -0
- package/api/users/index.js +109 -0
- package/dist/3rdpartylicenses.txt +1477 -0
- package/dist/Quicksand-Bold.071154c292aef0b8.woff +0 -0
- package/dist/Quicksand-Bold.6383d6475ed5c40f.woff2 +0 -0
- package/dist/Quicksand-Bold.f07d467887f9cfab.ttf +0 -0
- package/dist/Quicksand-Medium.0982a651e8d4315f.woff +0 -0
- package/dist/Quicksand-Medium.9d2733fbfb9b1be8.ttf +0 -0
- package/dist/Quicksand-Medium.b09302365c586eb2.woff2 +0 -0
- package/dist/Quicksand-Regular.16adf9eecd267273.woff +0 -0
- package/dist/Quicksand-Regular.78819724f6aeff59.woff2 +0 -0
- package/dist/Quicksand-Regular.8829564f0e14bf76.ttf +0 -0
- package/dist/assets/fonts/icomoon.eot +0 -0
- package/dist/assets/fonts/icomoon.svg +19 -0
- package/dist/assets/fonts/icomoon.ttf +0 -0
- package/dist/assets/fonts/icomoon.woff +0 -0
- package/dist/assets/fonts/myicons.eot +0 -0
- package/dist/assets/fonts/myicons.svg +19 -0
- package/dist/assets/fonts/myicons.ttf +0 -0
- package/dist/assets/fonts/myicons.woff +0 -0
- package/dist/assets/fonts/quicksand-bold/Quicksand-Bold.ttf +0 -0
- package/dist/assets/fonts/quicksand-bold/Quicksand-Bold.woff +0 -0
- package/dist/assets/fonts/quicksand-bold/Quicksand-Bold.woff2 +0 -0
- package/dist/assets/fonts/quicksand-medium/Quicksand-Medium.ttf +0 -0
- package/dist/assets/fonts/quicksand-medium/Quicksand-Medium.woff +0 -0
- package/dist/assets/fonts/quicksand-medium/Quicksand-Medium.woff2 +0 -0
- package/dist/assets/fonts/quicksand-regular/Quicksand-Regular.ttf +0 -0
- package/dist/assets/fonts/quicksand-regular/Quicksand-Regular.woff +0 -0
- package/dist/assets/fonts/quicksand-regular/Quicksand-Regular.woff2 +0 -0
- package/dist/assets/fonts/roboto-bold/roboto-bold-webfont.svg +10486 -0
- package/dist/assets/fonts/roboto-bold/roboto-bold-webfont.ttf +0 -0
- package/dist/assets/fonts/roboto-bold/roboto-bold-webfont.woff +0 -0
- package/dist/assets/fonts/roboto-bold/roboto-bold-webfont.woff2 +0 -0
- package/dist/assets/fonts/roboto-light/roboto-light-webfont.svg +9998 -0
- package/dist/assets/fonts/roboto-light/roboto-light-webfont.ttf +0 -0
- package/dist/assets/fonts/roboto-light/roboto-light-webfont.woff +0 -0
- package/dist/assets/fonts/roboto-light/roboto-light-webfont.woff2 +0 -0
- package/dist/assets/fonts/roboto-medium/roboto-medium-webfont.svg +10487 -0
- package/dist/assets/fonts/roboto-medium/roboto-medium-webfont.ttf +0 -0
- package/dist/assets/fonts/roboto-medium/roboto-medium-webfont.woff +0 -0
- package/dist/assets/fonts/roboto-medium/roboto-medium-webfont.woff2 +0 -0
- package/dist/assets/fonts/roboto-regular/roboto-regular-webfont.svg +10004 -0
- package/dist/assets/fonts/roboto-regular/roboto-regular-webfont.ttf +0 -0
- package/dist/assets/fonts/roboto-regular/roboto-regular-webfont.woff +0 -0
- package/dist/assets/fonts/roboto-regular/roboto-regular-webfont.woff2 +0 -0
- package/dist/assets/fonts/roboto-thin/roboto-thin-webfont.svg +10012 -0
- package/dist/assets/fonts/roboto-thin/roboto-thin-webfont.ttf +0 -0
- package/dist/assets/fonts/roboto-thin/roboto-thin-webfont.woff +0 -0
- package/dist/assets/fonts/roboto-thin/roboto-thin-webfont.woff2 +0 -0
- package/dist/assets/i18n/de.json +1308 -0
- package/dist/assets/i18n/en.json +1438 -0
- package/dist/assets/i18n/es.json +777 -0
- package/dist/assets/i18n/fr.json +1129 -0
- package/dist/assets/i18n/ko.json +774 -0
- package/dist/assets/i18n/pt.json +657 -0
- package/dist/assets/i18n/ru.json +1228 -0
- package/dist/assets/i18n/tr.json +673 -0
- package/dist/assets/i18n/ua.json +614 -0
- package/dist/assets/i18n/zh-cn.json +1252 -0
- package/dist/assets/images/align-bottom.svg +88 -0
- package/dist/assets/images/align-center.svg +86 -0
- package/dist/assets/images/align-left.svg +86 -0
- package/dist/assets/images/align-middle.svg +88 -0
- package/dist/assets/images/align-right.svg +88 -0
- package/dist/assets/images/align-top.svg +88 -0
- package/dist/assets/images/bag.svg +115 -0
- package/dist/assets/images/button.svg +22 -0
- package/dist/assets/images/chart.svg +17 -0
- package/dist/assets/images/circle.svg +84 -0
- package/dist/assets/images/compressor-a.svg +2 -0
- package/dist/assets/images/editvalue.svg +14 -0
- package/dist/assets/images/ellipse.svg +84 -0
- package/dist/assets/images/flip-orizontal.svg +86 -0
- package/dist/assets/images/flip-vertical.svg +82 -0
- package/dist/assets/images/gauge-donut.png +0 -0
- package/dist/assets/images/gauge-mat.png +0 -0
- package/dist/assets/images/gauge-zone.png +0 -0
- package/dist/assets/images/graphbar.svg +18 -0
- package/dist/assets/images/group.svg +91 -0
- package/dist/assets/images/iframe.svg +54 -0
- package/dist/assets/images/image.svg +95 -0
- package/dist/assets/images/led-circle.svg +77 -0
- package/dist/assets/images/line.svg +86 -0
- package/dist/assets/images/linecap-butt.svg +77 -0
- package/dist/assets/images/linecap-round.svg +77 -0
- package/dist/assets/images/linecap-square.svg +82 -0
- package/dist/assets/images/linejoin-bevel.svg +77 -0
- package/dist/assets/images/linejoin-miter.svg +77 -0
- package/dist/assets/images/linejoin-round.svg +77 -0
- package/dist/assets/images/logo.svg +18 -0
- package/dist/assets/images/path.svg +100 -0
- package/dist/assets/images/pencil.svg +98 -0
- package/dist/assets/images/pipe.svg +15 -0
- package/dist/assets/images/progress-v.svg +79 -0
- package/dist/assets/images/rect.svg +84 -0
- package/dist/assets/images/select-pointer.svg +93 -0
- package/dist/assets/images/selectvalue.svg +14 -0
- package/dist/assets/images/semaphore.svg +19 -0
- package/dist/assets/images/slider.svg +17 -0
- package/dist/assets/images/switch.svg +15 -0
- package/dist/assets/images/table.svg +55 -0
- package/dist/assets/images/text.svg +294 -0
- package/dist/assets/images/to-bottom.svg +163 -0
- package/dist/assets/images/to-path.svg +94 -0
- package/dist/assets/images/to-top.svg +163 -0
- package/dist/assets/images/to_top.svg +88 -0
- package/dist/assets/images/todelete.svg +13 -0
- package/dist/assets/images/ungroup.svg +108 -0
- package/dist/assets/images/value.svg +81 -0
- package/dist/assets/images/valve-a.svg +2 -0
- package/dist/assets/images/webcam.svg +16 -0
- package/dist/assets/lib/ext-styles.css +28 -0
- package/dist/assets/lib/gauge/gauge.js +988 -0
- package/dist/assets/lib/gauge/gauge.min.js +1 -0
- package/dist/assets/lib/nouislider/nouislider.min.css +1 -0
- package/dist/assets/lib/nouislider/nouislider.min.js +1 -0
- package/dist/assets/lib/numeral/locales.min.js +7 -0
- package/dist/assets/lib/numeral/numeral.min.js +8 -0
- package/dist/assets/lib/pdfkit-table/index.js +967 -0
- package/dist/assets/lib/svg/raphael.min.js +1 -0
- package/dist/assets/lib/svg/svg.js +5573 -0
- package/dist/assets/lib/svg/svg.min.js +13 -0
- package/dist/assets/lib/svgeditor/extensions/ext-bundle.min.js +1 -0
- package/dist/assets/lib/svgeditor/extensions/ext-html_button.min.css +1 -0
- package/dist/assets/lib/svgeditor/fuxa-editor.min.js +23 -0
- package/dist/assets/lib/svgeditor/jquery-plugin.min.css +2 -0
- package/dist/assets/lib/svgeditor/jquery-plugin.min.js +52 -0
- package/dist/assets/lib/svgeditor/jquery-ui-1.8.17.custom.min.js +54 -0
- package/dist/assets/lib/svgeditor/jquery.min.js +4 -0
- package/dist/assets/lib/svgeditor/shapes/ape-shapes.js +39 -0
- package/dist/assets/lib/svgeditor/shapes/img/agitator-disc.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/agitator-paddle.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/agitator-prop.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/agitator-turbo.svg +19 -0
- package/dist/assets/lib/svgeditor/shapes/img/anim-eli.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/anim-piston.svg +14 -0
- package/dist/assets/lib/svgeditor/shapes/img/centrifugal.svg +68 -0
- package/dist/assets/lib/svgeditor/shapes/img/centrifugal1.svg +67 -0
- package/dist/assets/lib/svgeditor/shapes/img/centrifuge1.svg +67 -0
- package/dist/assets/lib/svgeditor/shapes/img/centrifuge2.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/centrifuge3.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/centrifuge4.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/compair.svg +92 -0
- package/dist/assets/lib/svgeditor/shapes/img/compdiaph.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/compejector.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/compreci.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/compreci2.svg +68 -0
- package/dist/assets/lib/svgeditor/shapes/img/compressor-fan.svg +18 -0
- package/dist/assets/lib/svgeditor/shapes/img/compressor-piston.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/compressor-void.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/compring.svg +72 -0
- package/dist/assets/lib/svgeditor/shapes/img/compring2.svg +72 -0
- package/dist/assets/lib/svgeditor/shapes/img/comprotary.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/comprotary2.svg +18 -0
- package/dist/assets/lib/svgeditor/shapes/img/compscrew.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/compsilence.svg +20 -0
- package/dist/assets/lib/svgeditor/shapes/img/compturbo.svg +72 -0
- package/dist/assets/lib/svgeditor/shapes/img/crusher1.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/crusher2.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/crusher3.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/crusher4.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/crusher5.svg +18 -0
- package/dist/assets/lib/svgeditor/shapes/img/crusher6.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/crusher7.svg +21 -0
- package/dist/assets/lib/svgeditor/shapes/img/diaph.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/drier1.svg +63 -0
- package/dist/assets/lib/svgeditor/shapes/img/drier2.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/drier3.svg +23 -0
- package/dist/assets/lib/svgeditor/shapes/img/drier4.svg +18 -0
- package/dist/assets/lib/svgeditor/shapes/img/drier5.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger-filter.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger-heat.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger-tube.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger1.svg +67 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger2.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger3.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger4.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger5.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger6.svg +71 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger7.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger8.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/exchanger9.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/feeder.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/feeder2.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/feeder3.svg +63 -0
- package/dist/assets/lib/svgeditor/shapes/img/filter2.svg +68 -0
- package/dist/assets/lib/svgeditor/shapes/img/filter3.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting1.svg +67 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting10.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting11.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting12.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting13.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting2.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting3.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting4.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting5.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting6.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting7.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting8.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/fitting9.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/misc1.svg +75 -0
- package/dist/assets/lib/svgeditor/shapes/img/misc2.svg +71 -0
- package/dist/assets/lib/svgeditor/shapes/img/misc3.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/misc4.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/misc5.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/misc6.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/misc7.svg +64 -0
- package/dist/assets/lib/svgeditor/shapes/img/misc8.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/motor-simb.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/nozzle.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/nozzle2.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/pipi1.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/pipi2.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/pipi3.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/pipi4.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/pipi5.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/pipi6.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/pipi7.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpblower.svg +76 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpcentri1.svg +64 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpcentri2.svg +64 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpfeed.svg +64 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpgear.svg +18 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpgear2.svg +19 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumphidra.svg +68 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumphorizo.svg +68 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpjet.svg +68 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpperis.svg +20 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpscreew.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpscreew2.svg +72 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpturbi.svg +64 -0
- package/dist/assets/lib/svgeditor/shapes/img/pumpvacuum.svg +72 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-arrow.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-circle.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-circleindi.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-cloud.svg +63 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-cone.svg +71 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-corner.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-cross.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-cylinder.svg +71 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-delay.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-diamond.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-display.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-docu.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-doublearrow.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-drop.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-halfcircle.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-heart.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-looplimit.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-maninput.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-nosymbol.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-octagon.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-offpage.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-or.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-or2.svg +17 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-parallelogram.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-pentagon.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-poval.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-prepara.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-rectangle.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-rectindi.svg +16 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-star4.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-switch.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-tape.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-tee.svg +63 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-ticket.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-trape.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-triangle.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/shape-vor.svg +14 -0
- package/dist/assets/lib/svgeditor/shapes/img/tank1.svg +63 -0
- package/dist/assets/lib/svgeditor/shapes/img/tank2.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/tank3.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/tank4.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/tank5.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/tank6.svg +68 -0
- package/dist/assets/lib/svgeditor/shapes/img/tank7.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/tank8.svg +15 -0
- package/dist/assets/lib/svgeditor/shapes/img/tank9.svg +21 -0
- package/dist/assets/lib/svgeditor/shapes/img/valve-ax.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/valve-bx.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/valve-cx.svg +13 -0
- package/dist/assets/lib/svgeditor/shapes/img/webcam.svg +6 -0
- package/dist/assets/lib/svgeditor/shapes/my-shapes.js +178 -0
- package/dist/assets/lib/svgeditor/shapes/proc-comp-shapes.js +105 -0
- package/dist/assets/lib/svgeditor/shapes/proc-general-shapes.js +60 -0
- package/dist/assets/lib/svgeditor/shapes/proc-pumps-shapes.js +112 -0
- package/dist/assets/lib/svgeditor/shapes/proc-shapes.js +606 -0
- package/dist/assets/lib/svgeditor/shapes/shapes.js +30 -0
- package/dist/assets/lib/svgeditor/svg-editor.min.css +1 -0
- package/dist/assets/lib/uplot/placement.min.js +2 -0
- package/dist/assets/project.demo.fuxap +1 -0
- package/dist/favicon.ico +0 -0
- package/dist/icomoon.86abfb46e057ade8.eot +0 -0
- package/dist/icomoon.c1f8b59bad308d66.woff +0 -0
- package/dist/icomoon.ce427f75e21963af.ttf +0 -0
- package/dist/icomoon.dfb0a89feb346906.svg +19 -0
- package/dist/index.html +50 -0
- package/dist/logo.0e8e64e69250a450.svg +18 -0
- package/dist/main.a356f552d9838b9e.js +1 -0
- package/dist/material-icons-outlined.78a93b2079680a08.woff +0 -0
- package/dist/material-icons-outlined.f86cb7b0aa53f0fe.woff2 +0 -0
- package/dist/material-icons-round.92dc7ca2f4c591e7.woff +0 -0
- package/dist/material-icons-round.b10ec9db5b7fbc74.woff2 +0 -0
- package/dist/material-icons-sharp.3885863ee4746422.woff2 +0 -0
- package/dist/material-icons-sharp.a71cb2bf66c604de.woff +0 -0
- package/dist/material-icons-two-tone.588d63134de807a7.woff +0 -0
- package/dist/material-icons-two-tone.675bd578bd14533e.woff2 +0 -0
- package/dist/material-icons.4ad034d2c499d9b6.woff +0 -0
- package/dist/material-icons.59322316b3fd6063.woff2 +0 -0
- package/dist/polyfills.2696a6f9dc75535e.js +1 -0
- package/dist/roboto-bold-webfont.29ac6158e35aee95.woff +0 -0
- package/dist/roboto-bold-webfont.568ab1fa3f154a77.svg +10486 -0
- package/dist/roboto-bold-webfont.6bcfbdc216b3bc78.woff2 +0 -0
- package/dist/roboto-bold-webfont.7c22a4dfdee2ff33.ttf +0 -0
- package/dist/roboto-light-webfont.13492ec56771eeee.svg +9998 -0
- package/dist/roboto-light-webfont.61fa26c99b07ac83.woff2 +0 -0
- package/dist/roboto-light-webfont.95295ce84942d8ce.ttf +0 -0
- package/dist/roboto-light-webfont.ae19119a2889dfdf.woff +0 -0
- package/dist/roboto-medium-webfont.30344f0411888055.woff +0 -0
- package/dist/roboto-medium-webfont.57fb00cab0317d2d.woff2 +0 -0
- package/dist/roboto-medium-webfont.a40869e060a388c0.ttf +0 -0
- package/dist/roboto-medium-webfont.ea02241c29620c02.svg +10487 -0
- package/dist/roboto-regular-webfont.2b0501b72f5a94d5.ttf +0 -0
- package/dist/roboto-regular-webfont.2ce0ba9a06424965.svg +10004 -0
- package/dist/roboto-regular-webfont.ae47f6f1292d196f.woff2 +0 -0
- package/dist/roboto-regular-webfont.f58066a2d9061006.woff +0 -0
- package/dist/roboto-thin-webfont.0a64479870f676e8.ttf +0 -0
- package/dist/roboto-thin-webfont.0f7221f5c7e972ef.woff2 +0 -0
- package/dist/roboto-thin-webfont.51b221e22714b1fe.svg +10012 -0
- package/dist/roboto-thin-webfont.dac941649dd4eac0.woff +0 -0
- package/dist/runtime.8ef63094e52a66ba.js +1 -0
- package/dist/scripts.1c3385254ff4c93c.js +1 -0
- package/dist/styles.cf8e3cf50d039a5c.css +1 -0
- package/fuxa.js +39 -0
- package/main.js +381 -0
- package/package.json +68 -0
- package/paths.js +44 -0
- package/project.default.json +11 -0
- package/project.demo.fuxap +1 -0
- package/runtime/alarms/alarmstorage.js +205 -0
- package/runtime/alarms/index.js +678 -0
- package/runtime/devices/bacnet/index.js +730 -0
- package/runtime/devices/device-utils.js +95 -0
- package/runtime/devices/device.js +551 -0
- package/runtime/devices/ethernetip/index.js +381 -0
- package/runtime/devices/fuxaserver/index.js +310 -0
- package/runtime/devices/httprequest/index.js +495 -0
- package/runtime/devices/index.js +489 -0
- package/runtime/devices/modbus/datatypes.js +122 -0
- package/runtime/devices/modbus/index.js +730 -0
- package/runtime/devices/mqtt/index.js +618 -0
- package/runtime/devices/odbc/index.js +408 -0
- package/runtime/devices/opcua/index.js +817 -0
- package/runtime/devices/s7/datatypes.js +88 -0
- package/runtime/devices/s7/index.js +702 -0
- package/runtime/devices/template/index.js +141 -0
- package/runtime/events.js +33 -0
- package/runtime/index.js +559 -0
- package/runtime/jobs/cleaner.js +74 -0
- package/runtime/jobs/fonts/LICENSE.txt +202 -0
- package/runtime/jobs/fonts/Roboto-Black.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-BlackItalic.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-Bold.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-BoldItalic.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-Italic.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-Light.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-LightItalic.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-Medium.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-MediumItalic.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-Regular.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-Thin.ttf +0 -0
- package/runtime/jobs/fonts/Roboto-ThinItalic.ttf +0 -0
- package/runtime/jobs/helper/image-generator.js +82 -0
- package/runtime/jobs/index.js +214 -0
- package/runtime/jobs/report.js +353 -0
- package/runtime/logger.js +113 -0
- package/runtime/notificator/index.js +383 -0
- package/runtime/notificator/notifystorage.js +179 -0
- package/runtime/plugins/index.js +255 -0
- package/runtime/project/index.js +959 -0
- package/runtime/project/prjstorage.js +222 -0
- package/runtime/scripts/index.js +313 -0
- package/runtime/scripts/msm.js +146 -0
- package/runtime/storage/calculator.js +227 -0
- package/runtime/storage/daqstorage.js +188 -0
- package/runtime/storage/influxdb/index.js +240 -0
- package/runtime/storage/sqlite/currentstorage.js +144 -0
- package/runtime/storage/sqlite/index.js +695 -0
- package/runtime/storage/tdengine/index.js +106 -0
- package/runtime/users/index.js +123 -0
- package/runtime/users/usrstorage.js +201 -0
- package/runtime/utils.js +284 -0
- package/screenshot/feature-action-move.gif +0 -0
- package/screenshot/fuxa-ani.gif +0 -0
- package/screenshot/fuxa-device.gif +0 -0
- package/screenshot/fuxa-editor.png +0 -0
- package/screenshot/fuxa-hmi.gif +0 -0
- package/screenshot/fuxa-home.png +0 -0
- package/screenshot/fuxa-test.gif +0 -0
- package/settings.default.js +65 -0
|
@@ -0,0 +1,730 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 'modbus': modbus wrapper to communicate with PLC throw RTU/TCP
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
var ModbusRTU;
|
|
7
|
+
const datatypes = require('./datatypes');
|
|
8
|
+
const utils = require('../../utils');
|
|
9
|
+
const deviceUtils = require('../device-utils');
|
|
10
|
+
const TOKEN_LIMIT = 100;
|
|
11
|
+
|
|
12
|
+
function MODBUSclient(_data, _logger, _events) {
|
|
13
|
+
var memory = {}; // Loaded Signal grouped by memory { memory index, start, size, ... }
|
|
14
|
+
var data = JSON.parse(JSON.stringify(_data)); // Current Device data { id, name, tags, enabled, ... }
|
|
15
|
+
var logger = _logger;
|
|
16
|
+
var client = new ModbusRTU(); // Client Modbus (Master)
|
|
17
|
+
var working = false; // Working flag to manage overloading polling and connection
|
|
18
|
+
var events = _events; // Events to commit change to runtime
|
|
19
|
+
var lastStatus = ''; // Last Device status
|
|
20
|
+
var varsValue = []; // Signale to send to frontend { id, type, value }
|
|
21
|
+
var memItemsMap = {}; // Mapped Signale name with MemoryItem to find for set value
|
|
22
|
+
var mixItemsMap = {}; // Map the fragmented Signale { key = start address, value = MemoryItems }
|
|
23
|
+
var overloading = 0; // Overloading counter to mange the break connection
|
|
24
|
+
var lastTimestampValue; // Last Timestamp of asked values
|
|
25
|
+
var type;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* initialize the modubus type
|
|
29
|
+
*/
|
|
30
|
+
this.init = function (_type) {
|
|
31
|
+
type = _type;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Connect to PLC
|
|
36
|
+
* Emit connection status to clients, clear all Tags values
|
|
37
|
+
*/
|
|
38
|
+
this.connect = function () {
|
|
39
|
+
return new Promise(function (resolve, reject) {
|
|
40
|
+
if (data.property && data.property.address && (type === ModbusTypes.TCP ||
|
|
41
|
+
(type === ModbusTypes.RTU && data.property.baudrate && data.property.databits && data.property.stopbits && data.property.parity))) {
|
|
42
|
+
try {
|
|
43
|
+
if (!client.isOpen && _checkWorking(true)) {
|
|
44
|
+
logger.info(`'${data.name}' try to connect ${data.property.address}`, true);
|
|
45
|
+
_connect(function (err) {
|
|
46
|
+
if (err) {
|
|
47
|
+
logger.error(`'${data.name}' connect failed! ${err}`);
|
|
48
|
+
_emitStatus('connect-error');
|
|
49
|
+
_clearVarsValue();
|
|
50
|
+
reject();
|
|
51
|
+
} else {
|
|
52
|
+
if (data.property.slaveid) {
|
|
53
|
+
// set the client's unit id
|
|
54
|
+
client.setID(parseInt(data.property.slaveid));
|
|
55
|
+
}
|
|
56
|
+
// set a timout for requests default is null (no timeout)
|
|
57
|
+
client.setTimeout(2000);
|
|
58
|
+
logger.info(`'${data.name}' connected!`, true);
|
|
59
|
+
_emitStatus('connect-ok');
|
|
60
|
+
resolve();
|
|
61
|
+
}
|
|
62
|
+
_checkWorking(false);
|
|
63
|
+
});
|
|
64
|
+
} else {
|
|
65
|
+
reject();
|
|
66
|
+
_emitStatus('connect-error');
|
|
67
|
+
}
|
|
68
|
+
} catch (err) {
|
|
69
|
+
logger.error(`'${data.name}' try to connect error! ${err}`);
|
|
70
|
+
_checkWorking(false);
|
|
71
|
+
_emitStatus('connect-error');
|
|
72
|
+
_clearVarsValue();
|
|
73
|
+
reject();
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
logger.error(`'${data.name}' missing connection data!`);
|
|
77
|
+
_emitStatus('connect-failed');
|
|
78
|
+
_clearVarsValue();
|
|
79
|
+
reject();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Disconnect the PLC
|
|
86
|
+
* Emit connection status to clients, clear all Tags values
|
|
87
|
+
*/
|
|
88
|
+
this.disconnect = function () {
|
|
89
|
+
return new Promise(function (resolve, reject) {
|
|
90
|
+
_checkWorking(false);
|
|
91
|
+
if (!client.isOpen) {
|
|
92
|
+
_emitStatus('connect-off');
|
|
93
|
+
_clearVarsValue();
|
|
94
|
+
resolve(true);
|
|
95
|
+
} else {
|
|
96
|
+
client.close(function (result) {
|
|
97
|
+
if (result) {
|
|
98
|
+
logger.error(`'${data.name}' try to disconnect failed!`);
|
|
99
|
+
} else {
|
|
100
|
+
logger.info(`'${data.name}' disconnected!`, true);
|
|
101
|
+
}
|
|
102
|
+
_emitStatus('connect-off');
|
|
103
|
+
_clearVarsValue();
|
|
104
|
+
resolve(result);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Read values in polling mode
|
|
112
|
+
* Update the tags values list, save in DAQ if value changed or in interval and emit values to clients
|
|
113
|
+
*/
|
|
114
|
+
this.polling = async function () {
|
|
115
|
+
if (_checkWorking(true)) {
|
|
116
|
+
var readVarsfnc = [];
|
|
117
|
+
if (!data.property.options) {
|
|
118
|
+
for (var memaddr in memory) {
|
|
119
|
+
var tokenizedAddress = parseAddress(memaddr);
|
|
120
|
+
try {
|
|
121
|
+
readVarsfnc.push(await _readMemory(parseInt(tokenizedAddress.address), memory[memaddr].Start, memory[memaddr].MaxSize, Object.values(memory[memaddr].Items)));
|
|
122
|
+
readVarsfnc.push(await delay(data.property.delay || 10));
|
|
123
|
+
} catch (err) {
|
|
124
|
+
logger.error(`'${data.name}' _readMemory error! ${err}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
for (var memaddr in mixItemsMap) {
|
|
129
|
+
try {
|
|
130
|
+
readVarsfnc.push(await _readMemory(getMemoryAddress(parseInt(memaddr), false), mixItemsMap[memaddr].Start, mixItemsMap[memaddr].MaxSize, Object.values(mixItemsMap[memaddr].Items)));
|
|
131
|
+
readVarsfnc.push(await delay(data.property.delay || 10));
|
|
132
|
+
} catch (err) {
|
|
133
|
+
logger.error(`'${data.name}' _readMemory error! ${err}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// _checkWorking(false);
|
|
138
|
+
Promise.all(readVarsfnc).then(result => {
|
|
139
|
+
_checkWorking(false);
|
|
140
|
+
if (result.length) {
|
|
141
|
+
let varsValueChanged = _updateVarsValue(result);
|
|
142
|
+
lastTimestampValue = new Date().getTime();
|
|
143
|
+
_emitValues(varsValue);
|
|
144
|
+
if (this.addDaq && !utils.isEmptyObject(varsValueChanged)) {
|
|
145
|
+
this.addDaq(varsValueChanged, data.name, data.id);
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
// console.error('then error');
|
|
149
|
+
}
|
|
150
|
+
if (lastStatus !== 'connect-ok') {
|
|
151
|
+
_emitStatus('connect-ok');
|
|
152
|
+
}
|
|
153
|
+
}, reason => {
|
|
154
|
+
if (reason) {
|
|
155
|
+
if (reason.stack) {
|
|
156
|
+
logger.error(`'${data.name}' _readVars error! ${reason.stack}`);
|
|
157
|
+
} else if (reason.message) {
|
|
158
|
+
logger.error(`'${data.name}' _readVars error! ${reason.message}`);
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
logger.error(`'${data.name}' _readVars error! ${reason}`);
|
|
162
|
+
}
|
|
163
|
+
_checkWorking(false);
|
|
164
|
+
});
|
|
165
|
+
} else {
|
|
166
|
+
_emitStatus('connect-busy');
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Load Tags attribute to read with polling
|
|
172
|
+
*/
|
|
173
|
+
this.load = function (_data) {
|
|
174
|
+
data = JSON.parse(JSON.stringify(_data));
|
|
175
|
+
memory = {};
|
|
176
|
+
varsValue = [];
|
|
177
|
+
// memItemsMap = {};
|
|
178
|
+
mixItemsMap = {}; // Map the fragmented tag { key = start address, value = MemoryItems }
|
|
179
|
+
var stepsMap = {}; // Map the tag start address and size { key = start address, value = signal size and offset }
|
|
180
|
+
var count = 0;
|
|
181
|
+
for (var id in data.tags) {
|
|
182
|
+
try {
|
|
183
|
+
var offset = parseInt(data.tags[id].address) - 1; // because settings address from 1 to 65536 but communication start from 0
|
|
184
|
+
var token = Math.trunc(offset / TOKEN_LIMIT);
|
|
185
|
+
var memaddr = formatAddress(data.tags[id].memaddress, token);
|
|
186
|
+
if (!memory[memaddr]) {
|
|
187
|
+
memory[memaddr] = new MemoryItems();
|
|
188
|
+
}
|
|
189
|
+
if (!memory[memaddr].Items[offset]) {
|
|
190
|
+
memory[memaddr].Items[offset] = new MemoryItem(data.tags[id].type, offset);
|
|
191
|
+
}
|
|
192
|
+
memory[memaddr].Items[offset].Tags.push(data.tags[id]); // because you can have multiple tags at the same DB address
|
|
193
|
+
|
|
194
|
+
if (offset < memory[memaddr].Start) {
|
|
195
|
+
if (memory[memaddr].Start != 65536) {
|
|
196
|
+
memory[memaddr].MaxSize += memory[memaddr].Start - offset;
|
|
197
|
+
memory[memaddr].Start = offset;
|
|
198
|
+
} else {
|
|
199
|
+
memory[memaddr].MaxSize = datatypes[data.tags[id].type].WordLen;
|
|
200
|
+
memory[memaddr].Start = offset;
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
var len = offset + datatypes[data.tags[id].type].WordLen - memory[memaddr].Start;
|
|
204
|
+
if (memory[memaddr].MaxSize < len) {
|
|
205
|
+
memory[memaddr].MaxSize = len;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
memItemsMap[id] = memory[memaddr].Items[offset];
|
|
209
|
+
memItemsMap[id].format = data.tags[id].format;
|
|
210
|
+
stepsMap[parseInt(data.tags[id].memaddress) + offset] = { size: datatypes[data.tags[id].type].WordLen, offset: offset };
|
|
211
|
+
} catch (err) {
|
|
212
|
+
logger.error(`'${data.name}' load error! ${err}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// for fragmented
|
|
216
|
+
let lastStart = -1; // last start address
|
|
217
|
+
let lastMemAdr = -1;
|
|
218
|
+
let nextAdr = -1;
|
|
219
|
+
Object.keys(stepsMap).sort((a, b) => {return a - b; }).forEach(function(key) {
|
|
220
|
+
try {
|
|
221
|
+
var adr = parseInt(key); // tag address
|
|
222
|
+
let lastAdrSize = adr + stepsMap[key].size;
|
|
223
|
+
let offset = stepsMap[key].offset;
|
|
224
|
+
if (nextAdr < adr) {
|
|
225
|
+
// to fragment then new range
|
|
226
|
+
lastStart = adr;
|
|
227
|
+
let mits = new MemoryItems();
|
|
228
|
+
mits.Start = lastStart - getMemoryAddress(lastStart, false);
|
|
229
|
+
mits.MaxSize = lastAdrSize - lastStart;
|
|
230
|
+
var token = Math.trunc(offset / TOKEN_LIMIT);
|
|
231
|
+
lastMemAdr = getMemoryAddress(lastStart, true, token);
|
|
232
|
+
mits.Items = getMemoryItems(memory[lastMemAdr].Items, mits.Start, mits.MaxSize);
|
|
233
|
+
mixItemsMap[lastStart] = mits;
|
|
234
|
+
} else if (mixItemsMap[lastStart]) {
|
|
235
|
+
// to attach of exist range
|
|
236
|
+
mixItemsMap[lastStart].MaxSize = lastAdrSize - lastStart;
|
|
237
|
+
mixItemsMap[lastStart].Items = getMemoryItems(memory[lastMemAdr].Items, mixItemsMap[lastStart].Start, mixItemsMap[lastStart].MaxSize);
|
|
238
|
+
}
|
|
239
|
+
nextAdr = 1 + adr + stepsMap[key].size;
|
|
240
|
+
} catch (err) {
|
|
241
|
+
logger.error(`'${data.name}' load error! ${err}`);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
logger.info(`'${data.name}' data loaded (${count})`, true);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Return Tags values array { id: <name>, value: <value>, type: <type> }
|
|
249
|
+
*/
|
|
250
|
+
this.getValues = function () {
|
|
251
|
+
return varsValue;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Return Tag value { id: <name>, value: <value>, ts: <lastTimestampValue> }
|
|
256
|
+
*/
|
|
257
|
+
this.getValue = function (id) {
|
|
258
|
+
if (varsValue[id]) {
|
|
259
|
+
return {id: id, value: varsValue[id].value, ts: lastTimestampValue };
|
|
260
|
+
}
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Return connection status 'connect-off', 'connect-ok', 'connect-error'
|
|
266
|
+
*/
|
|
267
|
+
this.getStatus = function () {
|
|
268
|
+
return lastStatus;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Return Tag property
|
|
273
|
+
*/
|
|
274
|
+
this.getTagProperty = function (id) {
|
|
275
|
+
if (memItemsMap[id]) {
|
|
276
|
+
return { id: id, name: id, type: memItemsMap[id].type, format: memItemsMap[id].format };
|
|
277
|
+
} else {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Set the Tag value
|
|
284
|
+
* Read the current Tag object, write the value in object and send to SPS
|
|
285
|
+
*/
|
|
286
|
+
this.setValue = async function (sigid, value) {
|
|
287
|
+
if (data.tags[sigid]) {
|
|
288
|
+
var memaddr = data.tags[sigid].memaddress;
|
|
289
|
+
var offset = parseInt(data.tags[sigid].address) - 1; // because settings address from 1 to 65536 but communication start from 0
|
|
290
|
+
value = deviceUtils.tagRawCalculator(value, data.tags[sigid]);
|
|
291
|
+
var val = datatypes[data.tags[sigid].type].formatter(convertValue(value, data.tags[sigid].divisor, true));
|
|
292
|
+
if (type === ModbusTypes.RTU) {
|
|
293
|
+
const start = Date.now();
|
|
294
|
+
let now = start;
|
|
295
|
+
while ((now - start) < 3000 && working) { // wait max 3 seconds
|
|
296
|
+
now = Date.now();
|
|
297
|
+
await delay(20);
|
|
298
|
+
}
|
|
299
|
+
_checkWorking(true);
|
|
300
|
+
}
|
|
301
|
+
try {
|
|
302
|
+
await _writeMemory(parseInt(memaddr), offset, val).then(result => {
|
|
303
|
+
logger.info(`'${data.name}' setValue(${sigid}, ${value})`, true, true);
|
|
304
|
+
}, reason => {
|
|
305
|
+
if (reason && reason.stack) {
|
|
306
|
+
logger.error(`'${data.name}' _writeMemory error! ${reason.stack}`);
|
|
307
|
+
} else {
|
|
308
|
+
logger.error(`'${data.name}' _writeMemory error! ${reason}`);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
if (type === ModbusTypes.RTU) {
|
|
312
|
+
_checkWorking(false);
|
|
313
|
+
}
|
|
314
|
+
} catch (err) {
|
|
315
|
+
console.log(err);
|
|
316
|
+
}
|
|
317
|
+
return true;
|
|
318
|
+
} else {
|
|
319
|
+
logger.error(`'${data.name}' setValue(${sigid}, ${value}) Tag not found`, true, true);
|
|
320
|
+
}
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Return if PLC is connected
|
|
326
|
+
* Don't work if PLC will disconnect
|
|
327
|
+
*/
|
|
328
|
+
this.isConnected = function () {
|
|
329
|
+
return client.isOpen;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Bind the DAQ store function
|
|
334
|
+
*/
|
|
335
|
+
this.bindAddDaq = function (fnc) {
|
|
336
|
+
this.addDaq = fnc; // Add the DAQ value to db history
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
this.addDaq = null;
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Return the timestamp of last read tag operation on polling
|
|
343
|
+
* @returns
|
|
344
|
+
*/
|
|
345
|
+
this.lastReadTimestamp = () => {
|
|
346
|
+
return lastTimestampValue;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Return the Daq settings of Tag
|
|
351
|
+
* @returns
|
|
352
|
+
*/
|
|
353
|
+
this.getTagDaqSettings = (tagId) => {
|
|
354
|
+
return data.tags[tagId] ? data.tags[tagId].daq : null;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Set Daq settings of Tag
|
|
359
|
+
* @returns
|
|
360
|
+
*/
|
|
361
|
+
this.setTagDaqSettings = (tagId, settings) => {
|
|
362
|
+
if (data.tags[tagId]) {
|
|
363
|
+
utils.mergeObjectsValues(data.tags[tagId].daq, settings);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Connect with RTU or TCP
|
|
369
|
+
*/
|
|
370
|
+
var _connect = function(callback) {
|
|
371
|
+
try {
|
|
372
|
+
if (type === ModbusTypes.RTU) {
|
|
373
|
+
const rtuOptions = {
|
|
374
|
+
baudRate: parseInt(data.property.baudrate),
|
|
375
|
+
dataBits: parseInt(data.property.databits),
|
|
376
|
+
stopBits: parseFloat(data.property.stopbits),
|
|
377
|
+
parity: data.property.parity.toLowerCase()
|
|
378
|
+
}
|
|
379
|
+
if (data.property.connectionOption === ModbusOptionType.RTUBufferedPort) {
|
|
380
|
+
client.connectRTUBuffered(data.property.address, rtuOptions, callback);
|
|
381
|
+
} else if (data.property.connectionOption === ModbusOptionType.AsciiPort) {
|
|
382
|
+
client.connectAsciiSerial(data.property.address, rtuOptions, callback);
|
|
383
|
+
} else {
|
|
384
|
+
client.connectRTU(data.property.address, rtuOptions, callback);
|
|
385
|
+
}
|
|
386
|
+
} else if (type === ModbusTypes.TCP) {
|
|
387
|
+
var port = 502;
|
|
388
|
+
var addr = data.property.address;
|
|
389
|
+
if (data.property.address.indexOf(':') !== -1) {
|
|
390
|
+
var addr = data.property.address.substring(0, data.property.address.indexOf(':'));
|
|
391
|
+
var temp = data.property.address.substring(data.property.address.indexOf(':') + 1);
|
|
392
|
+
port = parseInt(temp);
|
|
393
|
+
}
|
|
394
|
+
if (data.property.connectionOption === ModbusOptionType.UdpPort) {
|
|
395
|
+
client.connectUDP(addr, { port: port }, callback)
|
|
396
|
+
} else if (data.property.connectionOption === ModbusOptionType.TcpRTUBufferedPort) {
|
|
397
|
+
client.connectTcpRTUBuffered(addr, { port: port }, callback)
|
|
398
|
+
} else if (data.property.connectionOption === ModbusOptionType.TelnetPort) {
|
|
399
|
+
client.connectTelnet(addr, { port: port }, callback)
|
|
400
|
+
} else {
|
|
401
|
+
client.connectTCP(addr, { port: port }, callback)
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
} catch (err) {
|
|
405
|
+
callback(err);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Read a Memory from modbus and parse the result
|
|
411
|
+
* @param {int} memoryAddress - The memory address to read
|
|
412
|
+
* @param {int} start - Position of the first variable
|
|
413
|
+
* @param {int} size - Length of the variables to read (the last address)
|
|
414
|
+
* @param {array} vars - Array of Var objects
|
|
415
|
+
* @returns {Promise} - Resolves to the vars array with populate *value* property
|
|
416
|
+
*/
|
|
417
|
+
var _readMemory = function (memoryAddress, start, size, vars) {
|
|
418
|
+
return new Promise((resolve, reject) => {
|
|
419
|
+
if (vars.length === 0) return resolve([]);
|
|
420
|
+
// define read function
|
|
421
|
+
if (memoryAddress === ModbusMemoryAddress.CoilStatus) { // Coil Status (Read/Write 000001-065536)
|
|
422
|
+
client.readCoils(start, size).then( res => {
|
|
423
|
+
if (res.data) {
|
|
424
|
+
vars.map(v => {
|
|
425
|
+
let bitoffset = Math.trunc((v.offset - start) / 8);
|
|
426
|
+
let bit = (v.offset - start) % 8;
|
|
427
|
+
let value = datatypes[v.type].parser(res.buffer, bitoffset, bit);
|
|
428
|
+
v.changed = value !== v.rawValue;
|
|
429
|
+
v.rawValue = value;
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
resolve(vars);
|
|
433
|
+
}, reason => {
|
|
434
|
+
reject(reason);
|
|
435
|
+
});
|
|
436
|
+
} else if (memoryAddress === ModbusMemoryAddress.DigitalInputs) { // Digital Inputs (Read 100001-165536)
|
|
437
|
+
client.readDiscreteInputs(start, size).then( res => {
|
|
438
|
+
if (res.data) {
|
|
439
|
+
vars.map(v => {
|
|
440
|
+
let bitoffset = Math.trunc((v.offset - start) / 8);
|
|
441
|
+
let bit = (v.offset - start) % 8;
|
|
442
|
+
let value = datatypes[v.type].parser(res.buffer, bitoffset, bit);
|
|
443
|
+
v.changed = value !== v.rawValue;
|
|
444
|
+
v.rawValue = value;
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
resolve(vars);
|
|
448
|
+
}, reason => {
|
|
449
|
+
reject(reason);
|
|
450
|
+
});
|
|
451
|
+
} else if (memoryAddress === ModbusMemoryAddress.InputRegisters) { // Input Registers (Read 300001-365536)
|
|
452
|
+
client.readInputRegisters(start, size).then( res => {
|
|
453
|
+
if (res.data) {
|
|
454
|
+
vars.map(v => {
|
|
455
|
+
try {
|
|
456
|
+
let byteoffset = (v.offset - start) * 2;
|
|
457
|
+
let buffer = Buffer.from(res.buffer.slice(byteoffset, byteoffset + datatypes[v.type].bytes))
|
|
458
|
+
let value = datatypes[v.type].parser(buffer);
|
|
459
|
+
v.changed = value !== v.rawValue;
|
|
460
|
+
v.rawValue = value;
|
|
461
|
+
} catch (err) {
|
|
462
|
+
console.error(err);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
resolve(vars);
|
|
467
|
+
}, reason => {
|
|
468
|
+
reject(reason);
|
|
469
|
+
});
|
|
470
|
+
} else if (memoryAddress === ModbusMemoryAddress.HoldingRegisters) { // Holding Registers (Read/Write 400001-465535)
|
|
471
|
+
client.readHoldingRegisters(start, size).then( res => {
|
|
472
|
+
if (res.data) {
|
|
473
|
+
vars.map(v => {
|
|
474
|
+
let byteoffset = (v.offset - start) * 2;
|
|
475
|
+
let buffer = Buffer.from(res.buffer.slice(byteoffset, byteoffset + datatypes[v.type].bytes))
|
|
476
|
+
let value = datatypes[v.type].parser(buffer);
|
|
477
|
+
v.changed = value !== v.rawValue;
|
|
478
|
+
v.rawValue = value;
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
resolve(vars);
|
|
482
|
+
}, reason => {
|
|
483
|
+
console.error(reason);
|
|
484
|
+
reject(reason);
|
|
485
|
+
});
|
|
486
|
+
} else {
|
|
487
|
+
reject();
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Write value to modbus
|
|
494
|
+
* @param {*} memoryAddress
|
|
495
|
+
* @param {*} start
|
|
496
|
+
* @param {*} value
|
|
497
|
+
*/
|
|
498
|
+
var _writeMemory = function (memoryAddress, start, value) {
|
|
499
|
+
return new Promise((resolve, reject) => {
|
|
500
|
+
if (memoryAddress === ModbusMemoryAddress.CoilStatus) { // Coil Status (Read/Write 000001-065536)
|
|
501
|
+
client.writeCoil(start, value).then(res => {
|
|
502
|
+
resolve();
|
|
503
|
+
}, reason => {
|
|
504
|
+
console.error(reason);
|
|
505
|
+
reject(reason);
|
|
506
|
+
});
|
|
507
|
+
} else if (memoryAddress === ModbusMemoryAddress.DigitalInputs) { // Digital Inputs (Read 100001-165536)
|
|
508
|
+
reject();
|
|
509
|
+
} else if (memoryAddress === ModbusMemoryAddress.InputRegisters) { // Input Registers (Read 300001-365536)
|
|
510
|
+
reject();
|
|
511
|
+
} else if (memoryAddress === ModbusMemoryAddress.HoldingRegisters) { // Holding Registers (Read/Write 400001-465535)
|
|
512
|
+
client.writeRegisters(start, value).then(res => {
|
|
513
|
+
resolve();
|
|
514
|
+
}, reason => {
|
|
515
|
+
console.error(reason);
|
|
516
|
+
reject(reason);
|
|
517
|
+
});
|
|
518
|
+
} else {
|
|
519
|
+
reject();
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Clear the Tags values by setting to null
|
|
526
|
+
* Emit to clients
|
|
527
|
+
*/
|
|
528
|
+
var _clearVarsValue = function () {
|
|
529
|
+
for (var id in varsValue) {
|
|
530
|
+
varsValue[id].value = null;
|
|
531
|
+
}
|
|
532
|
+
for (var id in memItemsMap) {
|
|
533
|
+
memItemsMap[id].value = null;
|
|
534
|
+
}
|
|
535
|
+
_emitValues(varsValue);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Update the Tags values read
|
|
540
|
+
* @param {*} vars
|
|
541
|
+
*/
|
|
542
|
+
var _updateVarsValue = (vars) => {
|
|
543
|
+
var someval = false;
|
|
544
|
+
var tempTags = {};
|
|
545
|
+
for (var vid in vars) {
|
|
546
|
+
let items = vars[vid];
|
|
547
|
+
for (var itemidx in items) {
|
|
548
|
+
const changed = items[itemidx].changed;
|
|
549
|
+
if (items[itemidx] instanceof MemoryItem) {
|
|
550
|
+
let type = items[itemidx].type;
|
|
551
|
+
let rawValue = items[itemidx].rawValue;
|
|
552
|
+
let tags = items[itemidx].Tags;
|
|
553
|
+
tags.forEach(tag => {
|
|
554
|
+
tempTags[tag.id] = {
|
|
555
|
+
id: tag.id,
|
|
556
|
+
rawValue: convertValue(rawValue, tag.divisor),
|
|
557
|
+
type: type,
|
|
558
|
+
daq: tag.daq,
|
|
559
|
+
changed: changed,
|
|
560
|
+
tagref: tag
|
|
561
|
+
};
|
|
562
|
+
someval = true;
|
|
563
|
+
});
|
|
564
|
+
} else {
|
|
565
|
+
tempTags[items[itemidx].id] = {
|
|
566
|
+
id: items[itemidx].id,
|
|
567
|
+
rawValue: items[itemidx].rawValue,
|
|
568
|
+
type: items[itemidx].type,
|
|
569
|
+
daq: items[itemidx].daq,
|
|
570
|
+
changed: changed,
|
|
571
|
+
tagref: items[itemidx]
|
|
572
|
+
};
|
|
573
|
+
someval = true;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (someval) {
|
|
578
|
+
const timestamp = new Date().getTime();
|
|
579
|
+
var result = {};
|
|
580
|
+
for (var id in tempTags) {
|
|
581
|
+
if (!utils.isNullOrUndefined(tempTags[id].rawValue)) {
|
|
582
|
+
tempTags[id].value = deviceUtils.tagValueCompose(tempTags[id].rawValue, tempTags[id].tagref);
|
|
583
|
+
tempTags[id].timestamp = timestamp;
|
|
584
|
+
if (this.addDaq && deviceUtils.tagDaqToSave(tempTags[id], timestamp)) {
|
|
585
|
+
result[id] = tempTags[id];
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
varsValue[id] = tempTags[id];
|
|
589
|
+
varsValue[id].changed = false;
|
|
590
|
+
}
|
|
591
|
+
return result;
|
|
592
|
+
}
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Emit the PLC Tags values array { id: <name>, value: <value>, type: <type> }
|
|
598
|
+
* @param {*} values
|
|
599
|
+
*/
|
|
600
|
+
var _emitValues = function (values) {
|
|
601
|
+
events.emit('device-value:changed', { id: data.id, values: values });
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Emit the PLC connection status
|
|
606
|
+
* @param {*} status
|
|
607
|
+
*/
|
|
608
|
+
var _emitStatus = function (status) {
|
|
609
|
+
lastStatus = status;
|
|
610
|
+
events.emit('device-status:changed', { id: data.id, status: status });
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Used to manage the async connection and polling automation (that not overloading)
|
|
615
|
+
* @param {*} check
|
|
616
|
+
*/
|
|
617
|
+
var _checkWorking = function (check) {
|
|
618
|
+
if (check && working) {
|
|
619
|
+
overloading++;
|
|
620
|
+
// !The driver don't give the break connection
|
|
621
|
+
if (overloading >= 3) {
|
|
622
|
+
if (type !== ModbusTypes.RTU) {
|
|
623
|
+
logger.warn(`'${data.name}' working (connection || polling) overload! ${overloading}`);
|
|
624
|
+
}
|
|
625
|
+
client.close();
|
|
626
|
+
} else {
|
|
627
|
+
return false;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
working = check;
|
|
631
|
+
overloading = 0;
|
|
632
|
+
return true;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
const formatAddress = function(address, token) { return token + '-' + address; }
|
|
636
|
+
const parseAddress = function(address) { return { token: address.split('-')[0], address: address.split('-')[1] }; }
|
|
637
|
+
const getMemoryAddress = function(address, askey, token) {
|
|
638
|
+
if (address < ModbusMemoryAddress.DigitalInputs) {
|
|
639
|
+
if (askey) {
|
|
640
|
+
return formatAddress('000000', token);
|
|
641
|
+
}
|
|
642
|
+
return ModbusMemoryAddress.CoilStatus;
|
|
643
|
+
} else if (address < ModbusMemoryAddress.InputRegisters) {
|
|
644
|
+
if (askey) {
|
|
645
|
+
return formatAddress(ModbusMemoryAddress.DigitalInputs, token);
|
|
646
|
+
}
|
|
647
|
+
return ModbusMemoryAddress.DigitalInputs;
|
|
648
|
+
} else if (address < ModbusMemoryAddress.HoldingRegisters) {
|
|
649
|
+
if (askey) {
|
|
650
|
+
return formatAddress(ModbusMemoryAddress.InputRegisters, token);
|
|
651
|
+
}
|
|
652
|
+
return ModbusMemoryAddress.InputRegisters;
|
|
653
|
+
} else {
|
|
654
|
+
if (askey) {
|
|
655
|
+
return formatAddress(ModbusMemoryAddress.HoldingRegisters, token);
|
|
656
|
+
}
|
|
657
|
+
return ModbusMemoryAddress.HoldingRegisters;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
const convertValue = function (value, divisor, tosrc = false) {
|
|
661
|
+
try {
|
|
662
|
+
if (divisor && parseFloat(divisor)) {
|
|
663
|
+
if (tosrc) {
|
|
664
|
+
return value * parseFloat(divisor);
|
|
665
|
+
} else {
|
|
666
|
+
return value / parseFloat(divisor);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
} catch (err) {
|
|
670
|
+
console.error(err);
|
|
671
|
+
}
|
|
672
|
+
return value;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Return the Items that are wit address and size in the range start, size
|
|
677
|
+
* @param {*} items
|
|
678
|
+
* @param {*} start
|
|
679
|
+
* @param {*} size
|
|
680
|
+
* @returns
|
|
681
|
+
*/
|
|
682
|
+
const getMemoryItems = function(items, start, size) {
|
|
683
|
+
let result = {};
|
|
684
|
+
for (var itemidx in items) {
|
|
685
|
+
if (items[itemidx].offset >= start && items[itemidx].offset < start + size) {
|
|
686
|
+
result[itemidx] = items[itemidx];
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
return result;
|
|
690
|
+
}
|
|
691
|
+
const delay = ms => { return new Promise(resolve => setTimeout(resolve, ms)) };
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
const ModbusTypes = { RTU: 0, TCP: 1 };
|
|
695
|
+
const ModbusMemoryAddress = { CoilStatus: 0, DigitalInputs: 100000, InputRegisters: 300000, HoldingRegisters: 400000 };
|
|
696
|
+
const ModbusOptionType = {
|
|
697
|
+
SerialPort: 'SerialPort',
|
|
698
|
+
RTUBufferedPort: 'RTUBufferedPort',
|
|
699
|
+
AsciiPort: 'AsciiPort',
|
|
700
|
+
TcpPort: 'TcpPort',
|
|
701
|
+
UdpPort: 'UdpPort',
|
|
702
|
+
TcpRTUBufferedPort: 'TcpRTUBufferedPort',
|
|
703
|
+
TelnetPort: 'TelnetPort'
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
module.exports = {
|
|
707
|
+
init: function (settings) {
|
|
708
|
+
// deviceCloseTimeout = settings.deviceCloseTimeout || 15000;
|
|
709
|
+
},
|
|
710
|
+
create: function (data, logger, events, manager) {
|
|
711
|
+
try { ModbusRTU = require('modbus-serial'); } catch { }
|
|
712
|
+
if (!ModbusRTU && manager) { try { ModbusRTU = manager.require('modbus-serial'); } catch { } }
|
|
713
|
+
if (!ModbusRTU) return null;
|
|
714
|
+
return new MODBUSclient(data, logger, events);
|
|
715
|
+
},
|
|
716
|
+
ModbusTypes: ModbusTypes
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
function MemoryItem(type, offset) {
|
|
720
|
+
this.offset = offset;
|
|
721
|
+
this.type = type;
|
|
722
|
+
this.bit = -1;
|
|
723
|
+
this.Tags = [];
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
function MemoryItems() {
|
|
727
|
+
this.Start = 65536;
|
|
728
|
+
this.MaxSize = 0;
|
|
729
|
+
this.Items = {};
|
|
730
|
+
}
|