123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- <template>
- <Splitpanes
- class="smart-splitter"
- :rtl="SIDEBAR_ON_LEFT && windowInnerWidth.x.value >= 768"
- :class="{
- '!flex-row-reverse': SIDEBAR_ON_LEFT && windowInnerWidth.x.value >= 768,
- }"
- :horizontal="!(windowInnerWidth.x.value >= 768)"
- >
- <Pane size="75" min-size="65" class="hide-scrollbar !overflow-auto">
- <Splitpanes class="smart-splitter" :horizontal="COLUMN_LAYOUT">
- <Pane
- :size="COLUMN_LAYOUT ? 45 : 50"
- class="hide-scrollbar !overflow-auto"
- >
- <AppSection label="request">
- <div
- class="bg-primary flex flex-col space-y-4 p-4 top-0 z-10 sticky"
- >
- <div class="space-x-2 flex-1 inline-flex">
- <input
- id="mqtt-url"
- v-model="url"
- type="url"
- autocomplete="off"
- spellcheck="false"
- class="bg-primaryLight border border-divider rounded text-secondaryDark w-full py-2 px-4 hover:border-dividerDark focus-visible:bg-transparent focus-visible:border-dividerDark"
- :placeholder="$t('mqtt.url')"
- :disabled="connectionState"
- @keyup.enter="validUrl ? toggleConnection() : null"
- />
- <ButtonPrimary
- id="connect"
- :disabled="!validUrl"
- class="w-32"
- :label="
- connectionState
- ? $t('action.disconnect')
- : $t('action.connect')
- "
- :loading="connectingState"
- @click.native="toggleConnection"
- />
- </div>
- <div class="flex space-x-4">
- <input
- id="mqtt-username"
- v-model="username"
- type="text"
- spellcheck="false"
- class="input"
- :placeholder="$t('authorization.username')"
- />
- <input
- id="mqtt-password"
- v-model="password"
- type="password"
- spellcheck="false"
- class="input"
- :placeholder="$t('authorization.password')"
- />
- </div>
- </div>
- </AppSection>
- </Pane>
- <Pane
- :size="COLUMN_LAYOUT ? 65 : 50"
- class="hide-scrollbar !overflow-auto"
- >
- <AppSection label="response">
- <RealtimeLog :title="$t('mqtt.log')" :log="log" />
- </AppSection>
- </Pane>
- </Splitpanes>
- </Pane>
- <Pane
- v-if="SIDEBAR"
- size="25"
- min-size="20"
- class="hide-scrollbar !overflow-auto"
- >
- <AppSection label="messages">
- <div class="flex flex-col flex-1 p-4 inline-flex">
- <label for="pub_topic" class="font-semibold text-secondaryLight">
- {{ $t("mqtt.topic") }}
- </label>
- </div>
- <div class="flex px-4">
- <input
- id="pub_topic"
- v-model="pub_topic"
- class="input"
- :placeholder="$t('mqtt.topic_name')"
- type="text"
- autocomplete="off"
- spellcheck="false"
- />
- </div>
- <div class="flex flex-1 p-4 items-center justify-between">
- <label for="mqtt-message" class="font-semibold text-secondaryLight">
- {{ $t("mqtt.communication") }}
- </label>
- </div>
- <div class="flex space-x-2 px-4">
- <input
- id="mqtt-message"
- v-model="msg"
- class="input"
- type="text"
- autocomplete="off"
- :placeholder="$t('mqtt.message')"
- spellcheck="false"
- />
- <ButtonPrimary
- id="publish"
- name="get"
- :disabled="!canpublish"
- :label="$t('mqtt.publish')"
- @click.native="publish"
- />
- </div>
- <div
- class="border-t border-dividerLight flex flex-col flex-1 mt-4 p-4 inline-flex"
- >
- <label for="sub_topic" class="font-semibold text-secondaryLight">
- {{ $t("mqtt.topic") }}
- </label>
- </div>
- <div class="flex space-x-2 px-4">
- <input
- id="sub_topic"
- v-model="sub_topic"
- type="text"
- autocomplete="off"
- :placeholder="$t('mqtt.topic_name')"
- spellcheck="false"
- class="input"
- />
- <ButtonPrimary
- id="subscribe"
- name="get"
- :disabled="!cansubscribe"
- :label="
- subscriptionState ? $t('mqtt.unsubscribe') : $t('mqtt.subscribe')
- "
- reverse
- @click.native="toggleSubscription"
- />
- </div>
- </AppSection>
- </Pane>
- </Splitpanes>
- </template>
- <script>
- import { defineComponent } from "@nuxtjs/composition-api"
- import { Splitpanes, Pane } from "splitpanes"
- import "splitpanes/dist/splitpanes.css"
- import Paho from "paho-mqtt"
- import debounce from "lodash/debounce"
- import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics"
- import { useSetting } from "~/newstore/settings"
- import useWindowSize from "~/helpers/utils/useWindowSize"
- import {
- MQTTEndpoint$,
- setMQTTEndpoint,
- MQTTConnectingState$,
- MQTTConnectionState$,
- setMQTTConnectingState,
- setMQTTConnectionState,
- MQTTSubscriptionState$,
- setMQTTSubscriptionState,
- MQTTSocket$,
- setMQTTSocket,
- MQTTLog$,
- setMQTTLog,
- addMQTTLogLine,
- } from "~/newstore/MQTTSession"
- import { useStream } from "~/helpers/utils/composables"
- export default defineComponent({
- components: { Splitpanes, Pane },
- setup() {
- return {
- windowInnerWidth: useWindowSize(),
- SIDEBAR: useSetting("SIDEBAR"),
- COLUMN_LAYOUT: useSetting("COLUMN_LAYOUT"),
- SIDEBAR_ON_LEFT: useSetting("SIDEBAR_ON_LEFT"),
- url: useStream(MQTTEndpoint$, "", setMQTTEndpoint),
- connectionState: useStream(
- MQTTConnectionState$,
- false,
- setMQTTConnectionState
- ),
- connectingState: useStream(
- MQTTConnectingState$,
- false,
- setMQTTConnectingState
- ),
- subscriptionState: useStream(
- MQTTSubscriptionState$,
- false,
- setMQTTSubscriptionState
- ),
- log: useStream(MQTTLog$, null, setMQTTLog),
- client: useStream(MQTTSocket$, null, setMQTTSocket),
- }
- },
- data() {
- return {
- isUrlValid: true,
- pub_topic: "",
- sub_topic: "",
- msg: "",
- manualDisconnect: false,
- username: "",
- password: "",
- }
- },
- computed: {
- validUrl() {
- return this.isUrlValid
- },
- canpublish() {
- return this.pub_topic !== "" && this.msg !== "" && this.connectionState
- },
- cansubscribe() {
- return this.sub_topic !== "" && this.connectionState
- },
- },
- watch: {
- url() {
- this.debouncer()
- },
- },
- created() {
- if (process.browser) {
- this.worker = this.$worker.createRejexWorker()
- this.worker.addEventListener("message", this.workerResponseHandler)
- }
- },
- destroyed() {
- this.worker.terminate()
- },
- methods: {
- debouncer: debounce(function () {
- this.worker.postMessage({ type: "ws", url: this.url })
- }, 1000),
- workerResponseHandler({ data }) {
- if (data.url === this.url) this.isUrlValid = data.result
- },
- connect() {
- this.connectingState = true
- this.log = [
- {
- payload: this.$t("state.connecting_to", { name: this.url }),
- source: "info",
- color: "var(--accent-color)",
- ts: new Date().toLocaleTimeString(),
- },
- ]
- const parseUrl = new URL(this.url)
- this.client = new Paho.Client(
- `${parseUrl.hostname}${
- parseUrl.pathname !== "/" ? parseUrl.pathname : ""
- }`,
- parseUrl.port !== "" ? Number(parseUrl.port) : 8081,
- "hoppscotch"
- )
- const connectOptions = {
- onSuccess: this.onConnectionSuccess,
- onFailure: this.onConnectionFailure,
- useSSL: parseUrl.protocol !== "ws:",
- }
- if (this.username !== "") {
- connectOptions.userName = this.username
- }
- if (this.password !== "") {
- connectOptions.password = this.password
- }
- this.client.connect(connectOptions)
- this.client.onConnectionLost = this.onConnectionLost
- this.client.onMessageArrived = this.onMessageArrived
- logHoppRequestRunToAnalytics({
- platform: "mqtt",
- })
- },
- onConnectionFailure() {
- this.connectingState = false
- this.connectionState = false
- addMQTTLogLine({
- payload: this.$t("error.something_went_wrong"),
- source: "info",
- color: "#ff5555",
- ts: new Date().toLocaleTimeString(),
- })
- },
- onConnectionSuccess() {
- this.connectingState = false
- this.connectionState = true
- addMQTTLogLine({
- payload: this.$t("state.connected_to", { name: this.url }),
- source: "info",
- color: "var(--accent-color)",
- ts: new Date().toLocaleTimeString(),
- })
- this.$toast.success(this.$t("state.connected"))
- },
- onMessageArrived({ payloadString, destinationName }) {
- addMQTTLogLine({
- payload: `Message: ${payloadString} arrived on topic: ${destinationName}`,
- source: "info",
- color: "var(--accent-color)",
- ts: new Date().toLocaleTimeString(),
- })
- },
- toggleConnection() {
- if (this.connectionState) {
- this.disconnect()
- } else {
- this.connect()
- }
- },
- disconnect() {
- this.manualDisconnect = true
- this.client.disconnect()
- addMQTTLogLine({
- payload: this.$t("state.disconnected_from", { name: this.url }),
- source: "info",
- color: "#ff5555",
- ts: new Date().toLocaleTimeString(),
- })
- },
- onConnectionLost() {
- this.connectingState = false
- this.connectionState = false
- if (this.manualDisconnect) {
- this.$toast.error(this.$t("state.disconnected"))
- } else {
- this.$toast.error(this.$t("error.something_went_wrong"))
- }
- this.manualDisconnect = false
- this.subscriptionState = false
- },
- publish() {
- try {
- this.client.publish(this.pub_topic, this.msg, 0, false)
- addMQTTLogLine({
- payload: `Published message: ${this.msg} to topic: ${this.pub_topic}`,
- ts: new Date().toLocaleTimeString(),
- source: "info",
- color: "var(--accent-color)",
- })
- } catch (e) {
- addMQTTLogLine({
- payload:
- this.$t("error.something_went_wrong") +
- `while publishing msg: ${this.msg} to topic: ${this.pub_topic}`,
- source: "info",
- color: "#ff5555",
- ts: new Date().toLocaleTimeString(),
- })
- }
- },
- toggleSubscription() {
- if (this.subscriptionState) {
- this.unsubscribe()
- } else {
- this.subscribe()
- }
- },
- subscribe() {
- try {
- this.client.subscribe(this.sub_topic, {
- onSuccess: this.usubSuccess,
- onFailure: this.usubFailure,
- })
- } catch (e) {
- addMQTTLogLine({
- payload:
- this.$t("error.something_went_wrong") +
- `while subscribing to topic: ${this.sub_topic}`,
- source: "info",
- color: "#ff5555",
- ts: new Date().toLocaleTimeString(),
- })
- }
- },
- usubSuccess() {
- this.subscriptionState = !this.subscriptionState
- addMQTTLogLine({
- payload:
- `Successfully ` +
- (this.subscriptionState ? "subscribed" : "unsubscribed") +
- ` to topic: ${this.sub_topic}`,
- source: "info",
- color: "var(--accent-color)",
- ts: new Date().toLocaleTimeString(),
- })
- },
- usubFailure() {
- addMQTTLogLine({
- payload:
- `Failed to ` +
- (this.subscriptionState ? "unsubscribe" : "subscribe") +
- ` to topic: ${this.sub_topic}`,
- source: "info",
- color: "#ff5555",
- ts: new Date().toLocaleTimeString(),
- })
- },
- unsubscribe() {
- this.client.unsubscribe(this.sub_topic, {
- onSuccess: this.usubSuccess,
- onFailure: this.usubFailure,
- })
- },
- },
- })
- </script>
|