Skip to content
Snippets Groups Projects
Commit f15fecc1 authored by Anze Skulj's avatar Anze Skulj
Browse files

Merge branch 'digital_twin' into 'main'

Digital twin

See merge request !1
parents 6e59a558 d5270fdb
No related branches found
No related tags found
1 merge request!1Digital twin
# This file excludes paths from the Docker build context.
#
# By default, Docker's build context includes all files (and folders) in the
# current directory. Even if a file isn't copied into the container it is still sent to
# the Docker daemon.
#
# There are multiple reasons to exclude files from the build context:
#
# 1. Prevent nested folders from being copied into the container (ex: exclude
# /assets/node_modules when copying /assets)
# 2. Reduce the size of the build context and improve build time (ex. /build, /deps, /doc)
# 3. Avoid sending files containing sensitive information
#
# More information on using .dockerignore is available here:
# https://docs.docker.com/engine/reference/builder/#dockerignore-file
.dockerignore
# Ignore git, but keep git HEAD and refs to access current commit hash if needed:
#
# $ cat .git/HEAD | awk '{print ".git/"$2}' | xargs cat
# d0b8727759e1e0e7aa3d41707d12376e373d5ecc
.git
!.git/HEAD
!.git/refs
# Common development/test artifacts
/cover/
/doc/
/test/
/tmp/
.elixir_ls
# Mix artifacts
/_build/
/deps/
*.ez
# Generated on crash by the VM
erl_crash.dump
# Static artifacts - These should be fetched and built inside the Docker image
/assets/node_modules/
/priv/static/assets/
/priv/static/cache_manifest.json
[
import_deps: [:ecto, :ecto_sql, :phoenix],
subdirectories: ["priv/*/migrations"],
plugins: [Phoenix.LiveView.HTMLFormatter],
inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}", "priv/*/seeds.exs"]
]
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
# Temporary files, for example, from tests.
/tmp/
# Ignore package tarball (built via "mix hex.build").
nemo_cloud_services-*.tar
# Ignore assets that are produced by build tools.
/priv/static/assets/
# Ignore digested assets cache.
/priv/static/cache_manifest.json
# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/
# Tomaz
/downloads/
# /firmware_files/
.env
\ No newline at end of file
include:
- project: 'eclipsefdn/it/releng/gitlab-runner-service/gitlab-ci-templates'
file: 'jobs/buildkit.gitlab-ci.yml'
- project: 'eclipsefdn/it/releng/gitlab-runner-service/gitlab-ci-templates'
file: 'pipeline-autodevops.gitlab-ci.yml'
stages:
- build
- test
variables:
CI_REGISTRY_IMAGE: nemometaos/fota
buildkit:
extends: .buildkit
# unit-test:
# stage: test
# script:
# - echo "Running unit tests... This will take about 10 seconds."
# # - docker run $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA /script/to/run/tests
# #- docker run $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA python -c "from src import common"
# # - sleep 10
# - echo "Tests passed succesfully!"
\ No newline at end of file
# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian
# instead of Alpine to avoid DNS resolution issues in production.
#
# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu
# https://hub.docker.com/_/ubuntu?tab=tags
#
# This file is based on these images:
#
# - https://hub.docker.com/r/hexpm/elixir/tags - for the build image
# - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20240904-slim - for the release image
# - https://pkgs.org/ - resource for finding needed packages
# - Ex: hexpm/elixir:1.17.2-erlang-27.0.1-debian-bullseye-20240904-slim
#
ARG ELIXIR_VERSION=1.17.2
ARG OTP_VERSION=27.0.1
ARG DEBIAN_VERSION=bullseye-20240904-slim
ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"
FROM ${BUILDER_IMAGE} as builder
# install build dependencies
RUN apt-get update -y && apt-get install -y build-essential git \
&& apt-get clean && rm -f /var/lib/apt/lists/*_*
# prepare build dir
WORKDIR /app
# install hex + rebar
RUN mix local.hex --force && \
mix local.rebar --force
# set build ENV
ENV MIX_ENV="prod"
ENV DATABASE_URL = "ecto://USER:PASS@HOST/DATABASE"
ENV SECRET_KEY_BASE = zYRQiZHSoacOEgsM9w0dW4YgMQeIOrHjlM63tkAdlTlHG6lXiCrkls2TD6khDliA
# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config
# copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies
# to be re-compiled.
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile
COPY priv priv
COPY lib lib
COPY assets assets
# compile assets
RUN mix assets.deploy
# Compile the release
RUN mix compile
# Changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/
COPY rel rel
RUN mix release
# start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM ${RUNNER_IMAGE}
RUN apt-get update -y && \
apt-get install -y libstdc++6 openssl libncurses5 locales ca-certificates \
&& apt-get clean && rm -f /var/lib/apt/lists/*_*
# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
WORKDIR "/app"
RUN chown nobody /app
# set runner ENV
ENV MIX_ENV="prod"
# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/nemo_cloud_services ./
USER nobody
# If using an environment that doesn't automatically reap zombie processes, it is
# advised to add an init process such as tini via `apt-get install`
# above and adding an entrypoint. See https://github.com/krallin/tini for details
# ENTRYPOINT ["/tini", "--"]
CMD ["/app/bin/server"]
......@@ -90,4 +90,4 @@ Show your appreciation to those who have contributed to the project.
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
\ No newline at end of file
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
/* This file is for your main application CSS */
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
// to get started and then uncomment the line below.
// import "./user_socket.js"
// You can include dependencies in two ways.
//
// The simplest option is to put them in assets/vendor and
// import them using relative paths:
//
// import "../vendor/some-package.js"
//
// Alternatively, you can `npm install some-package --prefix assets` and import
// them using a path starting with the package name:
//
// import "some-package"
//
// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
import "phoenix_html"
// Establish Phoenix Socket and LiveView configuration.
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
import topbar from "../vendor/topbar"
let Hooks = {}
Hooks.FlashMessage = {
mounted() {
setTimeout(() => {
this.pushEvent("clear_flash", { type: "info" })
}, 5000)
}
}
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {
longPollFallbackMs: 2500,
params: {_csrf_token: csrfToken},
hooks: Hooks
})
// Show progress bar on live navigation and form submits
topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
window.addEventListener("phx:page-loading-stop", _info => topbar.hide())
// connect if there are any LiveViews on the page
liveSocket.connect()
// expose liveSocket on window for web console debug logs and latency simulation:
// >> liveSocket.enableDebug()
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
// >> liveSocket.disableLatencySim()
window.liveSocket = liveSocket
{
"name": "assets",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"flowbite": "^2.5.2"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@rollup/plugin-node-resolve": {
"version": "15.3.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz",
"integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"@types/resolve": "1.20.2",
"deepmerge": "^4.2.2",
"is-module": "^1.0.0",
"resolve": "^1.22.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^2.78.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz",
"integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@types/estree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
},
"node_modules/@types/resolve": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"node_modules/flowbite": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/flowbite/-/flowbite-2.5.2.tgz",
"integrity": "sha512-kwFD3n8/YW4EG8GlY3Od9IoKND97kitO+/ejISHSqpn3vw2i5K/+ZI8Jm2V+KC4fGdnfi0XZ+TzYqQb4Q1LshA==",
"dependencies": {
"@popperjs/core": "^2.9.3",
"flowbite-datepicker": "^1.3.0",
"mini-svg-data-uri": "^1.4.3"
}
},
"node_modules/flowbite-datepicker": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/flowbite-datepicker/-/flowbite-datepicker-1.3.0.tgz",
"integrity": "sha512-CLVqzuoE2vkUvWYK/lJ6GzT0be5dlTbH3uuhVwyB67+PjqJWABm2wv68xhBf5BqjpBxvTSQ3mrmLHpPJ2tvrSQ==",
"dependencies": {
"@rollup/plugin-node-resolve": "^15.2.3",
"flowbite": "^2.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/is-core-module": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
"integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
"dependencies": {
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="
},
"node_modules/mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
"bin": {
"mini-svg-data-uri": "cli.js"
}
},
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
"dependencies": {
"is-core-module": "^2.13.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
}
}
}
{
"dependencies": {
"flowbite": "^2.5.2"
}
}
// See the Tailwind configuration guide for advanced usage
// https://tailwindcss.com/docs/configuration
const plugin = require("tailwindcss/plugin")
const fs = require("fs")
const path = require("path")
module.exports = {
content: [
"./js/**/*.js",
"../lib/nemo_cloud_services_web.ex",
"../lib/nemo_cloud_services_web/**/*.*ex"
],
theme: {
extend: {
colors: {
brand: "#FD4F00",
}
},
},
plugins: [
require("@tailwindcss/forms"),
// Allows prefixing tailwind classes with LiveView classes to add rules
// only when LiveView classes are applied, for example:
//
// <div class="phx-click-loading:animate-ping">
//
plugin(({addVariant}) => addVariant("phx-click-loading", [".phx-click-loading&", ".phx-click-loading &"])),
plugin(({addVariant}) => addVariant("phx-submit-loading", [".phx-submit-loading&", ".phx-submit-loading &"])),
plugin(({addVariant}) => addVariant("phx-change-loading", [".phx-change-loading&", ".phx-change-loading &"])),
// Embeds Heroicons (https://heroicons.com) into your app.css bundle
// See your `CoreComponents.icon/1` for more information.
//
plugin(function({matchComponents, theme}) {
let iconsDir = path.join(__dirname, "../deps/heroicons/optimized")
let values = {}
let icons = [
["", "/24/outline"],
["-solid", "/24/solid"],
["-mini", "/20/solid"],
["-micro", "/16/solid"]
]
icons.forEach(([suffix, dir]) => {
fs.readdirSync(path.join(iconsDir, dir)).forEach(file => {
let name = path.basename(file, ".svg") + suffix
values[name] = {name, fullPath: path.join(iconsDir, dir, file)}
})
})
matchComponents({
"hero": ({name, fullPath}) => {
let content = fs.readFileSync(fullPath).toString().replace(/\r?\n|\r/g, "")
let size = theme("spacing.6")
if (name.endsWith("-mini")) {
size = theme("spacing.5")
} else if (name.endsWith("-micro")) {
size = theme("spacing.4")
}
return {
[`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
"-webkit-mask": `var(--hero-${name})`,
"mask": `var(--hero-${name})`,
"mask-repeat": "no-repeat",
"background-color": "currentColor",
"vertical-align": "middle",
"display": "inline-block",
"width": size,
"height": size
}
}
}, {values})
})
]
}
/**
* @license MIT
* topbar 2.0.0, 2023-02-04
* https://buunguyen.github.io/topbar
* Copyright (c) 2021 Buu Nguyen
*/
(function (window, document) {
"use strict";
// https://gist.github.com/paulirish/1579671
(function () {
var lastTime = 0;
var vendors = ["ms", "moz", "webkit", "o"];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame =
window[vendors[x] + "RequestAnimationFrame"];
window.cancelAnimationFrame =
window[vendors[x] + "CancelAnimationFrame"] ||
window[vendors[x] + "CancelRequestAnimationFrame"];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function (callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function () {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function (id) {
clearTimeout(id);
};
})();
var canvas,
currentProgress,
showing,
progressTimerId = null,
fadeTimerId = null,
delayTimerId = null,
addEvent = function (elem, type, handler) {
if (elem.addEventListener) elem.addEventListener(type, handler, false);
else if (elem.attachEvent) elem.attachEvent("on" + type, handler);
else elem["on" + type] = handler;
},
options = {
autoRun: true,
barThickness: 3,
barColors: {
0: "rgba(26, 188, 156, .9)",
".25": "rgba(52, 152, 219, .9)",
".50": "rgba(241, 196, 15, .9)",
".75": "rgba(230, 126, 34, .9)",
"1.0": "rgba(211, 84, 0, .9)",
},
shadowBlur: 10,
shadowColor: "rgba(0, 0, 0, .6)",
className: null,
},
repaint = function () {
canvas.width = window.innerWidth;
canvas.height = options.barThickness * 5; // need space for shadow
var ctx = canvas.getContext("2d");
ctx.shadowBlur = options.shadowBlur;
ctx.shadowColor = options.shadowColor;
var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
for (var stop in options.barColors)
lineGradient.addColorStop(stop, options.barColors[stop]);
ctx.lineWidth = options.barThickness;
ctx.beginPath();
ctx.moveTo(0, options.barThickness / 2);
ctx.lineTo(
Math.ceil(currentProgress * canvas.width),
options.barThickness / 2
);
ctx.strokeStyle = lineGradient;
ctx.stroke();
},
createCanvas = function () {
canvas = document.createElement("canvas");
var style = canvas.style;
style.position = "fixed";
style.top = style.left = style.right = style.margin = style.padding = 0;
style.zIndex = 100001;
style.display = "none";
if (options.className) canvas.classList.add(options.className);
document.body.appendChild(canvas);
addEvent(window, "resize", repaint);
},
topbar = {
config: function (opts) {
for (var key in opts)
if (options.hasOwnProperty(key)) options[key] = opts[key];
},
show: function (delay) {
if (showing) return;
if (delay) {
if (delayTimerId) return;
delayTimerId = setTimeout(() => topbar.show(), delay);
} else {
showing = true;
if (fadeTimerId !== null) window.cancelAnimationFrame(fadeTimerId);
if (!canvas) createCanvas();
canvas.style.opacity = 1;
canvas.style.display = "block";
topbar.progress(0);
if (options.autoRun) {
(function loop() {
progressTimerId = window.requestAnimationFrame(loop);
topbar.progress(
"+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2)
);
})();
}
}
},
progress: function (to) {
if (typeof to === "undefined") return currentProgress;
if (typeof to === "string") {
to =
(to.indexOf("+") >= 0 || to.indexOf("-") >= 0
? currentProgress
: 0) + parseFloat(to);
}
currentProgress = to > 1 ? 1 : to;
repaint();
return currentProgress;
},
hide: function () {
clearTimeout(delayTimerId);
delayTimerId = null;
if (!showing) return;
showing = false;
if (progressTimerId != null) {
window.cancelAnimationFrame(progressTimerId);
progressTimerId = null;
}
(function loop() {
if (topbar.progress("+.1") >= 1) {
canvas.style.opacity -= 0.05;
if (canvas.style.opacity <= 0.05) {
canvas.style.display = "none";
fadeTimerId = null;
return;
}
}
fadeTimerId = window.requestAnimationFrame(loop);
})();
},
};
if (typeof module === "object" && typeof module.exports === "object") {
module.exports = topbar;
} else if (typeof define === "function" && define.amd) {
define(function () {
return topbar;
});
} else {
this.topbar = topbar;
}
}.call(this, window, document));
# This file is responsible for configuring your application
# and its dependencies with the aid of the Config module.
#
# This configuration file is loaded before any dependency and
# is restricted to this project.
# General application configuration
import Config
config :nemo_cloud_services,
ecto_repos: [NemoCloudServices.Repo],
generators: [timestamp_type: :utc_datetime]
# Configures the endpoint
config :nemo_cloud_services, NemoCloudServicesWeb.Endpoint,
url: [host: "localhost"],
adapter: Bandit.PhoenixAdapter,
render_errors: [
formats: [html: NemoCloudServicesWeb.ErrorHTML, json: NemoCloudServicesWeb.ErrorJSON],
layout: false
],
pubsub_server: NemoCloudServices.PubSub,
live_view: [signing_salt: "xJe2l6yb"]
# Configures the mailer
#
# By default it uses the "Local" adapter which stores the emails
# locally. You can see the emails in your browser, at "/dev/mailbox".
#
# For production it's recommended to configure a different adapter
# at the `config/runtime.exs`.
config :nemo_cloud_services, NemoCloudServices.Mailer, adapter: Swoosh.Adapters.Local
# Configure esbuild (the version is required)
config :esbuild,
version: "0.17.11",
nemo_cloud_services: [
args:
~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
]
# Configure tailwind (the version is required)
config :tailwind,
version: "3.4.3",
nemo_cloud_services: [
args: ~w(
--config=tailwind.config.js
--input=css/app.css
--output=../priv/static/assets/app.css
),
cd: Path.expand("../assets", __DIR__)
]
# Configures Elixir's Logger
config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]
# config :logger,
# backends: [{LoggerFileBackend, :info},
# {LoggerFileBackend, :error}]
# config :logger, :info,
# path: "debug.log",
# level: :info
# config :logger, :error,
# path: "error.log",
# level: :error
# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason
# TOMAZ
config :nemo_cloud_services,
:firmware_dir,
"firmware_files"
# CHECK THIS FOR mTLS -> https://www.emqx.com/en/blog/enable-two-way-ssl-for-emqx
config :nemo_cloud_services, :emqtt,
host: "192.168.6.115",
port: 1883,
clientid: System.get_env("MQTT_CLIENTID", "nemo_cloud_services"),
# clientid: :dynamic, # TA DYNAMIC DELA TEZAVE, iodata itd. mora biti kao string
clean_start: false,
name: :emqtt
config :nemo_cloud_services, :interval, 10_000
config :mime, :types, %{
"application/vnd.api+json" => ["hex", "fw"]
}
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs"
import Config
# Configure your database
config :nemo_cloud_services, NemoCloudServices.Repo,
username: "tomaz",
password: "zelosecuregeslo",
hostname: "192.168.1.15",
database: "nemo_cloud_services_dev",
stacktrace: true,
show_sensitive_data_on_connection_error: true,
pool_size: 10
# For development, we disable any cache and enable
# debugging and code reloading.
#
# The watchers configuration can be used to run external
# watchers to your application. For example, we can use it
# to bundle .js and .css sources.
config :nemo_cloud_services, NemoCloudServicesWeb.Endpoint,
# Binding to loopback ipv4 address prevents access from other machines.
# Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
# http: [ip: {127, 0, 0, 1}, port: 4000],
http: [ip: {0, 0, 0, 0}, port: 4000],
check_origin: false,
code_reloader: true,
debug_errors: true,
secret_key_base: "xKl0QJpZ77TFrTHFXBUZMAuKlRs/k27gUgggFULudM0UGjjkNueVvpAMI6mWr+hz",
watchers: [
esbuild: {Esbuild, :install_and_run, [:nemo_cloud_services, ~w(--sourcemap=inline --watch)]},
tailwind: {Tailwind, :install_and_run, [:nemo_cloud_services, ~w(--watch)]}
]
# ## SSL Support
#
# In order to use HTTPS in development, a self-signed
# certificate can be generated by running the following
# Mix task:
#
# mix phx.gen.cert
#
# Run `mix help phx.gen.cert` for more information.
#
# The `http:` config above can be replaced with:
#
# https: [
# port: 4001,
# cipher_suite: :strong,
# keyfile: "priv/cert/selfsigned_key.pem",
# certfile: "priv/cert/selfsigned.pem"
# ],
#
# If desired, both `http:` and `https:` keys can be
# configured to run both http and https servers on
# different ports.
# Watch static and templates for browser reloading.
config :nemo_cloud_services, NemoCloudServicesWeb.Endpoint,
live_reload: [
patterns: [
~r"priv/static/(?!uploads/).*(js|css|png|jpeg|jpg|gif|svg)$",
~r"priv/gettext/.*(po)$",
~r"lib/nemo_cloud_services_web/(controllers|live|components)/.*(ex|heex)$"
]
]
# Enable dev routes for dashboard and mailbox
config :nemo_cloud_services, dev_routes: true
# Do not include metadata nor timestamps in development logs
config :logger, :console, format: "[$level] $message\n"
# Set a higher stacktrace during development. Avoid configuring such
# in production as building large stacktraces may be expensive.
config :phoenix, :stacktrace_depth, 20
# Initialize plugs at runtime for faster development compilation
config :phoenix, :plug_init_mode, :runtime
config :phoenix_live_view,
# Include HEEx debug annotations as HTML comments in rendered markup
debug_heex_annotations: true,
# Enable helpful, but potentially expensive runtime checks
enable_expensive_runtime_checks: true
# Disable swoosh api client as it is only required for production adapters.
config :swoosh, :api_client, false
config :nemo_cloud_services, :keycloak,
url: "http://192.168.6.123:8080",
realm: "dedalus",
client_id: "dedalus-comsems-core",
client_secret: "wd2MXBhMsQehHsPSrt3uCJd4B9XD9ZaJ"
config :open_api_spex, :cache_adapter, OpenApiSpex.Plug.NoneCache
import Config
# Note we also include the path to a cache manifest
# containing the digested version of static files. This
# manifest is generated by the `mix assets.deploy` task,
# which you should run after static files are built and
# before starting your production server.
config :nemo_cloud_services, NemoCloudServicesWeb.Endpoint,
cache_static_manifest: "priv/static/cache_manifest.json"
# Configures Swoosh API Client
config :swoosh, api_client: Swoosh.ApiClient.Finch, finch_name: NemoCloudServices.Finch
# Disable Swoosh Local Memory Storage
config :swoosh, local: false
# Do not print debug messages in production
config :logger, level: :info
# Runtime production configuration, including reading
# of environment variables, is done on config/runtime.exs.
import Config
# config/runtime.exs is executed for all environments, including
# during releases. It is executed after compilation and before the
# system starts, so it is typically used to load production configuration
# and secrets from environment variables or elsewhere. Do not define
# any compile-time configuration in here, as it won't be applied.
# The block below contains prod specific runtime configuration.
# ## Using releases
#
# If you use `mix release`, you need to explicitly enable the server
# by passing the PHX_SERVER=true when you start it:
#
# PHX_SERVER=true bin/nemo_cloud_services start
#
# Alternatively, you can use `mix phx.gen.release` to generate a `bin/server`
# script that automatically sets the env var above.
if System.get_env("PHX_SERVER") do
config :nemo_cloud_services, NemoCloudServicesWeb.Endpoint, server: true
end
if config_env() == :prod do
database_url =
System.get_env("DATABASE_URL") ||
raise """
environment variable DATABASE_URL is missing.
For example: ecto://USER:PASS@HOST/DATABASE
"""
maybe_ipv6 = if System.get_env("ECTO_IPV6") in ~w(true 1), do: [:inet6], else: []
config :nemo_cloud_services, NemoCloudServices.Repo,
# ssl: true,
url: database_url,
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
socket_options: maybe_ipv6
# The secret key base is used to sign/encrypt cookies and other secrets.
# A default value is used in config/dev.exs and config/test.exs but you
# want to use a different value for prod and you most likely don't want
# to check this value into version control, so we use an environment
# variable instead.
secret_key_base =
System.get_env("SECRET_KEY_BASE") ||
raise """
environment variable SECRET_KEY_BASE is missing.
You can generate one by calling: mix phx.gen.secret
"""
host = System.get_env("PHX_HOST") || "example.com"
port = String.to_integer(System.get_env("PORT") || "4000")
config :nemo_cloud_services, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY")
config :nemo_cloud_services, NemoCloudServicesWeb.Endpoint,
url: [host: host, port: 443, scheme: "https"],
http: [
# Enable IPv6 and bind on all interfaces.
# Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.
# See the documentation on https://hexdocs.pm/bandit/Bandit.html#t:options/0
# for details about using IPv6 vs IPv4 and loopback vs public addresses.
ip: {0, 0, 0, 0, 0, 0, 0, 0},
port: port
],
secret_key_base: secret_key_base
# ## SSL Support
#
# To get SSL working, you will need to add the `https` key
# to your endpoint configuration:
#
# config :nemo_cloud_services, NemoCloudServicesWeb.Endpoint,
# https: [
# ...,
# port: 443,
# cipher_suite: :strong,
# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")
# ]
#
# The `cipher_suite` is set to `:strong` to support only the
# latest and more secure SSL ciphers. This means old browsers
# and clients may not be supported. You can set it to
# `:compatible` for wider support.
#
# `:keyfile` and `:certfile` expect an absolute path to the key
# and cert in disk or a relative path inside priv, for example
# "priv/ssl/server.key". For all supported SSL configuration
# options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1
#
# We also recommend setting `force_ssl` in your config/prod.exs,
# ensuring no data is ever sent via http, always redirecting to https:
#
# config :nemo_cloud_services, NemoCloudServicesWeb.Endpoint,
# force_ssl: [hsts: true]
#
# Check `Plug.SSL` for all available options in `force_ssl`.
# ## Configuring the mailer
#
# In production you need to configure the mailer to use a different adapter.
# Also, you may need to configure the Swoosh API client of your choice if you
# are not using SMTP. Here is an example of the configuration:
#
# config :nemo_cloud_services, NemoCloudServices.Mailer,
# adapter: Swoosh.Adapters.Mailgun,
# api_key: System.get_env("MAILGUN_API_KEY"),
# domain: System.get_env("MAILGUN_DOMAIN")
#
# For this example you need include a HTTP client required by Swoosh API client.
# Swoosh supports Hackney and Finch out of the box:
#
# config :swoosh, :api_client, Swoosh.ApiClient.Hackney
#
# See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details.
end
import Config
# Configure your database
#
# The MIX_TEST_PARTITION environment variable can be used
# to provide built-in test partitioning in CI environment.
# Run `mix help test` for more information.
config :nemo_cloud_services, NemoCloudServices.Repo,
username: "postgres",
password: "postgres",
hostname: "localhost",
database: "nemo_cloud_services_test#{System.get_env("MIX_TEST_PARTITION")}",
pool: Ecto.Adapters.SQL.Sandbox,
pool_size: System.schedulers_online() * 2
# We don't run a server during test. If one is required,
# you can enable the server option below.
config :nemo_cloud_services, NemoCloudServicesWeb.Endpoint,
http: [ip: {127, 0, 0, 1}, port: 4002],
secret_key_base: "fKxZWDEMSywwOtK1PPklOcTC9VYX3xCEkRQp3vmUnaCVyuuxI+CMVKzMNYWkJn4n",
server: false
# In test we don't send emails
config :nemo_cloud_services, NemoCloudServices.Mailer, adapter: Swoosh.Adapters.Test
# Disable swoosh api client as it is only required for production adapters
config :swoosh, :api_client, false
# Print only warnings and errors during test
config :logger, level: :warning
# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime
# Enable helpful, but potentially expensive runtime checks
config :phoenix_live_view,
enable_expensive_runtime_checks: true
## TODO
- all sceanrios for when GW start (electicity ON/OFF, LTE ON/OFF, LAN ON/OFF?? )
- Check all this scenarios before deployment of GWs
- Check supervision tree configuration
- Check access to GW over ssh/scp/mqtt/ws?
- Put in place mTLS for security and use that with all tests required
## 0.) Connectivity
- PMU : GW => TCP LAN
- GW : Cloud => LTE !!!! a lot of data !!! :)
## 1.) After reboot
```mermaid
sequenceDiagram
participant PMU
participant GW
participant MQTT BROKER
participant CLOUD SERVICE
PMU <<->> GW: TCP connection over LAN
Note right of CLOUD SERVICE: Hosted on NEMO cloud / K8s
Note over PMU, GW: c37xy protocol
GW->>MQTT BROKER:Connect to broker / mTLS
activate MQTT BROKER
MQTT BROKER --> GW: Persistent connection established
deactivate MQTT BROKER
CLOUD SERVICE->>MQTT BROKER: Connect to broker / mTLS
activate MQTT BROKER
MQTT BROKER --> CLOUD SERVICE: Persistent connection established
Note over GW, MQTT BROKER: Connect to data, admin, admin ack topics
Note over CLOUD SERVICE, MQTT BROKER: Connect to data, admin, admin ack topics
```
## 2.) Firmware change flow
- Developer of FW builds a new version of firmware and uses a UI to upload it to defined location
- In UI you can see this new Firmware under list of available firmwares
- You can choose a device and select a Firmare that this device should have (Perhaps already at it, or downgrade? or upgrade)
- When new Firmare (FW) is picked a message to MQTT broker topic `admin` should be send with predefined key and firmware id/name should be send. Take into the consideration that not all devices need this message (topic names) [{"firmware_change": {"gw": ["gw1", "gw2", ...], "target_firmware": "new_firmware_v1.2.fw"}}]
!!!! WARNING !!!! this logic has changed. device will only get itself as gateway. it will just double check if it is really for it. Server side is responsible to send correct messages to the right devices. So each device (from the list that came from UI) will get its own message to its own topic
[{"firmware_change": {"gw": device_id, "target_firmware": "new_firmware_v1.2.fw"}}]
#
- On a Gateway (GW) side functionality should be in place to pattern match this specific message and act accordingly. In this case, a part of code responsible for FW download should get this specific .fw file from predefined location and download it to GW.
- Then inplace upgrade should be done
- !! double check logic for writing and having information about current fw. Perhaps in some config file? This needs to be available for requests from cloud side (another message to admin topic / report this at GW startup) [{"firmware_info": {"version": "current_firmware_v1.2", ...}}]
- WRITE FW VERSION INTO THE FIRMWARE ITSELF so that it is available when you boot into the new partition so you can report back to /admin/ack
- GW will reboot after successful migration and when fully operational again it should send `ack` to Cloud so that GW status is updated accordingly in DB. [{"firmware_change_ack": {"status": "successful upgrade", "current_version": "current_firmware_v1.2", ... }}]
## 3.) Show measurement data - last 100 records
- GW will collect data from PMU at 50Hz (baje) and this data should be send further to cloud over MQTT
- `If needed` data can be pushed further to other destinations. [{"device_id": "nek GW UUID", "timestamp": 12143434356, "data": {payload}}]
## 4.) Get detailed measurement data on request from Cloud
- When event is triggered data with +/- delta TIME should be available to push/fetch from a GW to Cloud [{"data_request": {"start_time": 23232323232, "end_time": 434343434343}}]
- Brainstorm about using /data partition on GW with SCP or MQTT or WS?
- Check if request needs to go to both GWs!?!?
## 5.) Event detection and notification of Cloud side
- Implement (Denis) handler for observing and detecting data treshold violations.
- If detected -> notify cloud service. This is a requirement for detailed measurement data request (see above 4) [{"check_data_event": {"timestamp": 121213424, "event_at": ["V", ... ]}}]
#
#
#
#
## TESTING
#
#
#
#
NemoCloudServices.Conn.MqttClient.send_firmware_change(["nemo_gw_host", "nemo_gw_1"], "zero2wledota-500ms-v0.9.0.fw")
NemoCloudServices.Conn.MqttClient.send_firmware_change(["nemo_gw_host", "nemo_gw_1"], "zero2wledota-2000ms-v0.8.0.fw")
debug.log 0 → 100644
13:01:27.320 [info] Sent firmware change message to gateway nemo_gw_1 on topic nemo/pilot/nemo_gw_1/admin
13:01:27.324 [info] Received message on topic: nemo/pilot/nemo_gw_1/admin
13:01:27.324 [info] Payload: "{\"firmware_change\":{\"gw\":[\"nemo_gw_1\"],\"target_firmware\":\"zero2wledota-500ms-v0.1.0.fw\"}}"
13:01:27.324 [info] Handling admin message from client nemo_gw_1
13:02:16.529 [info] GET /firmwares
13:02:16.607 [info] Sent 200 in 78ms
13:02:16.629 [info] CONNECTED TO Phoenix.LiveView.Socket in 47µs
Transport: :longpoll
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"_csrf_token" => "CiBXMQAdHCY-ImElFwMFGxZlARtBKD0eGh3dwIWbOt1lcwcYbTXlvIx3", "_live_referer" => "undefined", "_mounts" => "1", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
13:02:17.199 [info] CONNECTED TO Phoenix.LiveView.Socket in 43µs
Transport: :websocket
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"_csrf_token" => "AD0wHQYXCBM_JgUbQg4HbzZELRFFGRBnMuTHqCCWNpUR6za-ButfrxUJ", "_live_referer" => "undefined", "_mounts" => "0", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
13:03:59.294 [error] ** (Bandit.HTTPError) Header read socket error: :closed
13:03:59.294 [error] ** (Bandit.HTTPError) Header read socket error: :closed
13:03:59.656 [info] GET /firmwares
13:03:59.657 [info] Sent 200 in 1ms
13:04:00.175 [info] CONNECTED TO Phoenix.LiveView.Socket in 19µs
Transport: :websocket
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"_csrf_token" => "eTIdAkQyCA8IICB8RQcHDRt9ChBtMxIf4zyW3fCKyvp51saOoLSgZRW2", "_live_referer" => "undefined", "_mounts" => "0", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
13:05:49.993 [error] ** (Bandit.HTTPError) Header read timeout
13:05:50.110 [error] ** (Bandit.HTTPError) Header read timeout
13:08:04.131 [info] Sent firmware change message to gateway nemo_gw_2 on topic nemo/pilot/nemo_gw_2/admin
13:08:04.134 [info] Received message on topic: nemo/pilot/nemo_gw_2/admin
13:08:04.134 [info] Payload: "{\"firmware_change\":{\"gw\":[\"nemo_gw_2\"],\"target_firmware\":\"zero2wledota-500ms-v0.1.0.fw\"}}"
13:08:04.134 [info] Handling admin message from client nemo_gw_2
13:09:23.447 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.676.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.676.0>, timer: #Reference<0.273484736.1227620354.225357>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:09:23.459 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.676.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.676.0>, timer: #Reference<0.273484736.1227620355.222122>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:09:23.461 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.676.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.676.0>, timer: #Reference<0.273484736.1227620355.222140>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:09:23.463 [info] Shutting down 1 sockets in 1 rounds of 2000ms
13:09:23.471 [info] Shutting down 1 sockets in 1 rounds of 2000ms
13:09:23.484 [info] Application nemo_cloud_services exited: shutdown
13:09:59.511 [info] Running NemoCloudServicesWeb.Endpoint with Bandit 1.5.7 at 127.0.0.1:4000 (http)
13:09:59.522 [info] Access NemoCloudServicesWeb.Endpoint at http://localhost:4000
13:09:59.668 [info] Subscribed to topics successfully
13:10:00.354 [info] CONNECTED TO Phoenix.LiveView.Socket in 43µs
Transport: :longpoll
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"_csrf_token" => "eTIdAkQyCA8IICB8RQcHDRt9ChBtMxIf4zyW3fCKyvp51saOoLSgZRW2", "_live_referer" => "undefined", "_mounts" => "0", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
13:10:17.150 [info] GET /firmwares
13:10:17.205 [info] Sent 200 in 54ms
13:10:17.676 [info] CONNECTED TO Phoenix.LiveView.Socket in 2ms
Transport: :websocket
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"_csrf_token" => "Pjg-MT8nfgYDEiUbNUEMcwVcFDt6FyR0spZdHs5BrDuRA5j1qmMLMvaY", "_live_referer" => "undefined", "_mounts" => "0", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
13:10:29.747 [info] GET /firmwares
13:10:29.751 [info] Sent 200 in 3ms
13:10:29.758 [info] GET /firmwares
13:10:29.759 [info] Sent 200 in 1ms
13:10:30.151 [info] CONNECTED TO Phoenix.LiveView.Socket in 20µs
Transport: :websocket
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"_csrf_token" => "AzgRDRYBGzwnEwANAB0zGz5gGy0OFT1XNpuXaUPxVEPDtiUYJQBZ9txz", "_live_referer" => "undefined", "_mounts" => "0", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
13:11:03.083 [info] GET /firmwares
13:11:03.087 [info] Sent 200 in 4ms
13:11:03.092 [info] GET /firmwares
13:11:03.094 [info] Sent 200 in 2ms
13:11:03.519 [info] CONNECTED TO Phoenix.LiveView.Socket in 47µs
Transport: :websocket
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"_csrf_token" => "Gz0RJRI6fTUQCTd6EDALBCJkEhRuNyF4Vuupen6qa_g3dDmFVUKcYVdU", "_live_referer" => "undefined", "_mounts" => "0", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
13:11:10.295 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.689.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.689.0>, timer: #Reference<0.2060872916.3379036163.112031>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:11:10.307 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.689.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.689.0>, timer: #Reference<0.2060872916.3379036162.108820>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:11:10.309 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.689.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.689.0>, timer: #Reference<0.2060872916.3379036161.102981>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:11:10.311 [info] Shutting down 1 sockets in 1 rounds of 2000ms
13:11:10.318 [info] Shutting down 1 sockets in 1 rounds of 2000ms
13:11:08.210 [info] CONNECTED TO Phoenix.LiveView.Socket in 39µs
Transport: :longpoll
Serializer: Phoenix.Socket.V2.JSONSerializer
Parameters: %{"_csrf_token" => "Gz0RJRI6fTUQCTd6EDALBCJkEhRuNyF4Vuupen6qa_g3dDmFVUKcYVdU", "_live_referer" => "undefined", "_mounts" => "0", "_track_static" => %{"0" => "http://localhost:4000/assets/app.css", "1" => "http://localhost:4000/assets/app.js"}, "vsn" => "2.0.0"}
13:11:08.222 [info] Application nemo_cloud_services exited: shutdown
error.log 0 → 100644
11:02:40.250 [error] ** (Bandit.HTTPError) Header read timeout
11:11:22.990 [error] GenServer #PID<0.812.0> terminating
** (KeyError) key :log_lines not found in: %{
socket: #Phoenix.LiveView.Socket<
id: "phx-GAMzTAF0RP8C-AAH",
endpoint: NemoCloudServicesWeb.Endpoint,
view: NemoCloudServicesWeb.OTAUpdateLive,
parent_pid: nil,
root_pid: #PID<0.812.0>,
router: NemoCloudServicesWeb.Router,
assigns: #Phoenix.LiveView.Socket.AssignsNotInSocket<>,
transport_pid: #PID<0.797.0>,
...
>,
__changed__: %{current_view: true},
flash: %{},
devices: [
%{
"nerves_fw_devpath" => "/dev/mmcblk0",
"b.nerves_fw_uuid" => "650297be-77f1-5e16-64bc-6828169c39ba",
"b.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_misc" => "",
"nerves_serial_number" => "",
:file_size => 118.4,
"a.nerves_fw_application_part0_fstype" => "ext4",
"b.nerves_fw_application_part0_target" => "/root",
"a.nerves_fw_architecture" => "arm",
"b.nerves_fw_description" => "",
:version => "v2.1.574-rev",
"a.nerves_fw_application_part0_target" => "/root",
"b.nerves_fw_product" => "zero2wledota",
"a.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_platform" => "rpi3a",
"b.nerves_fw_application_part0_fstype" => "ext4",
:online => true,
"b.nerves_fw_architecture" => "arm",
"a.nerves_fw_product" => "zero2wledota",
"nerves_fw_active" => "a",
"a.nerves_fw_description" => "",
"a.nerves_fw_uuid" => "0129700c-66bf-5097-7725-014698e9c855",
"b.nerves_fw_platform" => "rpi3a",
"a.nerves_fw_vcs_identifier" => "",
"b.nerves_fw_misc" => "",
"b.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3",
:id => "nemo_gw_1",
"a.nerves_fw_version" => "0.1.0",
:name => "NEMO GW 1",
"b.nerves_fw_version" => "0.1.0",
"b.nerves_fw_vcs_identifier" => "",
:type => "GW",
"a.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3"
},
%{
"nerves_fw_devpath" => "/dev/mmcblk0",
"b.nerves_fw_uuid" => "650297be-77f1-5e16-64bc-6828169c39ba",
"b.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_misc" => "",
"nerves_serial_number" => "",
:file_size => 118.4,
"a.nerves_fw_application_part0_fstype" => "ext4",
"b.nerves_fw_application_part0_target" => "/root",
"a.nerves_fw_architecture" => "arm",
"b.nerves_fw_description" => "",
:version => "v1.1",
"a.nerves_fw_application_part0_target" => "/root",
"b.nerves_fw_product" => "zero2wledota",
"a.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_platform" => "rpi3a",
"b.nerves_fw_application_part0_fstype" => "ext4",
:online => true,
"b.nerves_fw_architecture" => "arm",
"a.nerves_fw_product" => "zero2wledota",
"nerves_fw_active" => "a",
"a.nerves_fw_description" => "",
"a.nerves_fw_uuid" => "0129700c-66bf-5097-7725-014698e9c855",
"b.nerves_fw_platform" => "rpi3a",
"a.nerves_fw_vcs_identifier" => "",
"b.nerves_fw_misc" => "",
"b.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3",
:id => "nemo_gw_2",
"a.nerves_fw_version" => "0.1.0",
:name => "NEMO GW 2",
"b.nerves_fw_version" => "0.1.0",
"b.nerves_fw_vcs_identifier" => "",
:type => "GW",
"a.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3"
},
%{
"nerves_fw_devpath" => "/dev/mmcblk0",
"b.nerves_fw_uuid" => "650297be-77f1-5e16-64bc-6828169c39ba",
"b.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_misc" => "",
"nerves_serial_number" => "",
:file_size => 118.4,
"a.nerves_fw_application_part0_fstype" => "ext4",
"b.nerves_fw_application_part0_target" => "/root",
"a.nerves_fw_architecture" => "arm",
"b.nerves_fw_description" => "",
:version => "v1.1",
"a.nerves_fw_application_part0_target" => "/root",
"b.nerves_fw_product" => "zero2wledota",
"a.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_platform" => "rpi3a",
"b.nerves_fw_application_part0_fstype" => "ext4",
:online => false,
"b.nerves_fw_architecture" => "arm",
"a.nerves_fw_product" => "zero2wledota",
"nerves_fw_active" => "a",
"a.nerves_fw_description" => "",
"a.nerves_fw_uuid" => "0129700c-66bf-5097-7725-014698e9c855",
"b.nerves_fw_platform" => "rpi3a",
"a.nerves_fw_vcs_identifier" => "",
"b.nerves_fw_misc" => "",
"b.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3",
:id => "3",
"a.nerves_fw_version" => "0.1.0",
:name => "Sensor 43QTR",
"b.nerves_fw_version" => "0.1.0",
"b.nerves_fw_vcs_identifier" => "",
:type => "MISC",
"a.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3"
},
%{
"nerves_fw_devpath" => "/dev/mmcblk0",
"b.nerves_fw_uuid" => "650297be-77f1-5e16-64bc-6828169c39ba",
"b.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_misc" => "",
"nerves_serial_number" => "",
:file_size => 118.4,
"a.nerves_fw_application_part0_fstype" => "ext4",
"b.nerves_fw_application_part0_target" => "/root",
"a.nerves_fw_architecture" => "arm",
"b.nerves_fw_description" => "",
:version => "v1.1",
"a.nerves_fw_application_part0_target" => "/root",
"b.nerves_fw_product" => "zero2wledota",
"a.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_platform" => "rpi3a",
"b.nerves_fw_application_part0_fstype" => "ext4",
:online => true,
"b.nerves_fw_architecture" => "arm",
"a.nerves_fw_product" => "zero2wledota",
"nerves_fw_active" => "a",
"a.nerves_fw_description" => "",
"a.nerves_fw_uuid" => "0129700c-66bf-5097-7725-014698e9c855",
"b.nerves_fw_platform" => "rpi3a",
"a.nerves_fw_vcs_identifier" => "",
"b.nerves_fw_misc" => "",
"b.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3",
:id => "4",
"a.nerves_fw_version" => "0.1.0",
:name => "Sensor 43QTR",
"b.nerves_fw_version" => "0.1.0",
"b.nerves_fw_vcs_identifier" => "",
:type => "MISC",
"a.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3"
},
%{
"nerves_fw_devpath" => "/dev/mmcblk0",
"b.nerves_fw_uuid" => "650297be-77f1-5e16-64bc-6828169c39ba",
"b.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_misc" => "",
"nerves_serial_number" => "",
:file_size => 118.4,
"a.nerves_fw_application_part0_fstype" => "ext4",
"b.nerves_fw_application_part0_target" => "/root",
"a.nerves_fw_architecture" => "arm",
"b.nerves_fw_description" => "",
:version => "v1.1",
"a.nerves_fw_application_part0_target" => "/root",
"b.nerves_fw_product" => "zero2wledota",
"a.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_platform" => "rpi3a",
"b.nerves_fw_application_part0_fstype" => "ext4",
:online => false,
"b.nerves_fw_architecture" => "arm",
"a.nerves_fw_product" => "zero2wledota",
"nerves_fw_active" => "a",
"a.nerves_fw_description" => "",
"a.nerves_fw_uuid" => "0129700c-66bf-5097-7725-014698e9c855",
"b.nerves_fw_platform" => "rpi3a",
"a.nerves_fw_vcs_identifier" => "",
"b.nerves_fw_misc" => "",
"b.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3",
:id => "5",
"a.nerves_fw_version" => "0.1.0",
:name => "Sensor 43QTR",
"b.nerves_fw_version" => "0.1.0",
"b.nerves_fw_vcs_identifier" => "",
:type => "MISC",
"a.nerves_fw_application_part0_devpath" => "/dev/mmcblk0p3"
},
%{
"nerves_fw_devpath" => "/dev/mmcblk0",
"b.nerves_fw_uuid" => "650297be-77f1-5e16-64bc-6828169c39ba",
"b.nerves_fw_author" => "The Nerves Team",
"a.nerves_fw_misc" => "",
"nerves_serial_number" => "",
:file_size => 118.4,
"a.nerves_fw_application_part0_fstype" => "ext4",
"b.nerves_fw_application_part0_target" => "/root",
"a.nerve (truncated)
11:13:58.646 [error] ** (Bandit.HTTPError) Header read socket error: :closed
11:13:58.646 [error] ** (Bandit.HTTPError) Header read socket error: :closed
11:23:34.243 [error] ** (Bandit.HTTPError) Header read timeout
12:42:08.277 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.787.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.787.0>, timer: #Reference<0.2505205769.1750335492.202890>, interval: 10000, data_topic: "nemo/pilot/+/data", admin_topic: "nemo/pilot/+/admin", admin_ack_topic: "nemo/pilot/+/admin/ack"}
12:42:08.330 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.787.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.787.0>, timer: #Reference<0.2505205769.1750335491.188141>, interval: 10000, data_topic: "nemo/pilot/+/data", admin_topic: "nemo/pilot/+/admin", admin_ack_topic: "nemo/pilot/+/admin/ack"}
12:42:08.331 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.787.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.787.0>, timer: #Reference<0.2505205769.1750335491.188158>, interval: 10000, data_topic: "nemo/pilot/+/data", admin_topic: "nemo/pilot/+/admin", admin_ack_topic: "nemo/pilot/+/admin/ack"}
13:03:59.294 [error] ** (Bandit.HTTPError) Header read socket error: :closed
13:03:59.294 [error] ** (Bandit.HTTPError) Header read socket error: :closed
13:05:49.993 [error] ** (Bandit.HTTPError) Header read timeout
13:05:50.110 [error] ** (Bandit.HTTPError) Header read timeout
13:09:23.447 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.676.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.676.0>, timer: #Reference<0.273484736.1227620354.225357>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:09:23.459 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.676.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.676.0>, timer: #Reference<0.273484736.1227620355.222122>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:09:23.461 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.676.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.676.0>, timer: #Reference<0.273484736.1227620355.222140>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:11:10.295 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.689.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.689.0>, timer: #Reference<0.2060872916.3379036163.112031>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:11:10.307 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.689.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.689.0>, timer: #Reference<0.2060872916.3379036162.108820>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
13:11:10.309 [error] GenServer NemoCloudServices.Conn.MqttClient terminating
** (stop) exited in: :gen_statem.call(#PID<0.689.0>, {:connect, :emqtt_sock}, :infinity)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(stdlib 6.0.1) gen.erl:247: :gen.do_call/4
(stdlib 6.0.1) gen_statem.erl:2633: :gen_statem.call/3
(nemo_cloud_services 0.1.0) lib/nemo_cloud_services/conn/mqtt_client.ex:74: NemoCloudServices.Conn.MqttClient.handle_continue/2
(stdlib 6.0.1) gen_server.erl:2163: :gen_server.try_handle_continue/3
(stdlib 6.0.1) gen_server.erl:2072: :gen_server.loop/7
(stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
Last message: {:continue, :start_emqtt}
State: %{pid: #PID<0.689.0>, timer: #Reference<0.2060872916.3379036161.102981>, interval: 10000, admin_ack_topic: "nemo/pilot/+/admin/ack", admin_topic: "nemo/pilot/+/admin", data_topic: "nemo/pilot/+/data"}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment