/* * Copyright (C) 2016 The Qt Company Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import QtQuick 2.6 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.0 import QtWebSockets 1.0 import '..' SettingPage { id: root icon: '/bluetooth/images/HMI_Settings_BluetoothIcon.svg' title: 'Bluetooth' checkable: true readonly property bool isBluetooth: true property string btAPIpath: bindingAddress + '/Bluetooth-manager/' property var jsonObjectBT: [] property string currentState: 'idle' property string btState: 'off' //add property to indicate the bt status property string initDevice: 'N' property string address_str: bindingAddressWS property string token_str: "" property string api_str: "Bluetooth-Manager" property string verb_str: "" property var parameterJson: 'None' property string payloadLength: "9999" property var msgid_enu: { "call": 2, "retok": 3, "reterr": 4, "event": 5 } property string request_str: "" property string status_str: "" property int pairedDeviceCount property bool btOn:false WebSocket { id: websocket url: address_str onTextMessageReceived: { var message_json = JSON.parse(message); //console.log("Raw response: " + message) //console.log("JSON response: " + message_json) if (message_json[0] === msgid_enu.reterr) { console.log("Return value is not OK!") return } else if ((message_json[0] === msgid_enu.event)){ var eventContent = JSON.parse(JSON.stringify(message_json[2])) if (eventContent.event === "Bluetooth-Manager/device_added"){ //jsonObjectBT.add(eventContent.data) //btDeviceList.clear() console.log("BT list refreshed") initDevice = 'Y' if(eventContent.data.Paired==="True"){ pairedDeviceList.append({ deviceAddress: eventContent.data.Address, deviceName: eventContent.data.Name, devicePairable:eventContent.data.Paired, deviceConnect: eventContent.data.Connected, connectAVP: eventContent.data.AVPConnected, connectHFP: eventContent.data.HFPConnected, textToShow: "" }) pairedDeviceCount=pairedDeviceCount+1 } else btDeviceList.append({ deviceAddress: eventContent.data.Address, deviceName: eventContent.data.Name, devicePairable:eventContent.data.Paired, deviceConnect: eventContent.data.Connected, connectAVP: eventContent.data.AVPConnected, connectHFP: eventContent.data.HFPConnected, textToShow: "" }) } else if(eventContent.event === "Bluetooth-Manager/device_removed"){ if (findDevice(eventContent.data.Address) >= 0){ btDeviceList.remove(findDevice(eventContent.data.Address)) } else if(findPairDevice(eventContent.data.Address) >= 0){ pairedDeviceList.remove(findPairDevice(eventContent.data.Address)) pairedDeviceCount=pairedDeviceCount-1 } } else if(eventContent.event === "Bluetooth-Manager/device_updated"){ updateDeviceAttribute(eventContent.data) } else if(eventContent.event === "Bluetooth-Manager/request_confirmation"){ request(btAPIpath + "send_confirmation?value=yes", function (o) { console.log(o.responseText) }) } } if ((verb_str == "connect") || (verb_str == "refresh")) { token_str = message_json[3] } else if (verb_str == "logout") { token_str = "" websocket.active = false console.log("close socket") } } onStatusChanged: { if (websocket.status == WebSocket.Error) { status_str = "Error: " + websocket.errorString } else if (websocket.status == WebSocket.Open) { status_str = "Socket opened; sending message..." if (verb_str == "connect"){ WebSocket.sendTextMessage (request_str) } sendSocketMesage("subscribe", { value: "device_updated" }) sendSocketMesage("subscribe", { value: "device_added" }) sendSocketMesage("subscribe", { value: "device_removed" }) sendSocketMesage("subscribe", { value: "request_confirmation" }) } else if (websocket.status == WebSocket.Closed) { status_str = "Socket closed" } } active: false } Text { id: log anchors.fill: parent anchors.margins: 10 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } onCheckedChanged: { console.log("Bluetooth set to", checked) if (checked == true) { pairedDeviceCount=0 initBTlist() btOn=true request(btAPIpath + 'power?value=1', function (o) { // log the json response console.log(o.responseText) websocket.active = true }) request(btAPIpath + 'set_property?Property=Discoverable\&value=true', function (o) { console.log(o.responseText) }) request(btAPIpath + 'set_property?Property=Pairable\&value=true', function (o) { console.log(o.responseText) }) request(btAPIpath + 'start_discovery', function (o) { console.log(o.responseText) }) buttonScan.text = "STOP" //when power on and after send the discovery command, button set to STOP currentState = 'discovering' btState = 'on' //bt is on } else { btDeviceList.clear() pairedDeviceList.clear() pairedDeviceCount=0 btOn=false request(btAPIpath + 'stop_discovery', function (o) { // log the json response console.log(o.responseText) }) request(btAPIpath + 'power?value=0', function (o) { // log the json response console.log(o.responseText) }) buttonScan.text = "SEARCH" //when power off the button should be set to SEARCH currentState = 'idle' btState = 'off' //bt off websocket.active = false } } function sendSocketMesage(verb, parameter) { var requestJson = [msgid_enu.call, payloadLength, api_str + '/' + verb, parameter] websocket.sendTextMessage(JSON.stringify(requestJson)) } ListModel { id: pairedDeviceList } ListModel { id: btDeviceList } Rectangle { anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom anchors.margins: 80 width: buttonScan.width + 10 height: buttonScan.height + 10 color: "#222" border.color: "white" Button { id: buttonScan anchors.centerIn: parent width: 100 text: "SEARCH" //default value is SEARCH MouseArea { //id: mouseArea anchors.fill: parent onClicked: { if (buttonScan.text == "SEARCH"){ if (btState == 'on'){ //only response to the requirement when bt is on request(btAPIpath + 'start_discovery', function (o) { // log the json response console.log(o.responseText) }) buttonScan.text = "STOP" currentState = 'discovering' } }else{ request(btAPIpath + 'stop_discovery', function (o) { // log the json response console.log(o.responseText) }) buttonScan.text = "SEARCH" currentState = 'idle' } } } } } function request(url, callback) { var xhr = new XMLHttpRequest() xhr.onreadystatechange = (function (myxhr) { return function () { if (xhr.readyState == 4 && xhr.status == 200){ callback(myxhr) } } })(xhr) xhr.open('GET', url, false) xhr.send('') } Component { id:blueToothDevice Rectangle { height: 120 width: parent.width color: "transparent" MouseArea { anchors.fill: parent Column { anchors.left: parent.left anchors.leftMargin: 80 TextMetrics { id: textMetrics font.family: "Arial" elide: Text.ElideRight elideWidth: 140 text: deviceName } Text { id: btName text: textMetrics.elidedText color: '#66FF99' font.pixelSize: 48 } Text { id: btStatus property string connectionState:"" text: { if ((devicePairable === "True") && (deviceConnect === "True") && (connectAVP === "True") && (connectHFP === "False")) text = " AV Connection, " else if ((devicePairable === "True") && (deviceConnect === "True") && (connectHFP === "True") && (connectAVP === "False")) text = " Handsfree Connection, " else if ((devicePairable === "True") && (deviceConnect === "True") && (connectHFP === "True") && (connectAVP === "True")) text = " Handsfree & AV Connection, " else text = connectionState if (initDevice === "Y") { textToShow = text text = deviceAddress + text initDevice = 'N' } else { text = deviceAddress + textToShow } } font.pixelSize: 18 color: "#ffffff" font.italic: true } Text { id: btPairable text: devicePairable visible: false } Text { id: btConnectstatus text: deviceConnect visible: false } } Button { id: removeButton anchors.top:parent.top anchors.topMargin: 15 //anchors.horizontalCenter: btName.horizontalCenter anchors.right: parent.right anchors.rightMargin: 100 text: "Remove" MouseArea { anchors.fill: parent onClicked: { request(btAPIpath + 'remove_device?value=' + deviceAddress, function (o) { console.log(o.responseText) }) if (findDevice(deviceAddress) >= 0) btDeviceList.remove(findDevice(deviceAddress)) else if (findPairDevice(deviceAddress) >= 0){ pairedDeviceList.remove(findPairDevice(deviceAddress)) pairedDeviceCount=pairedDeviceCount-1 } } } } Button { id: connectButton anchors.top:parent.top anchors.topMargin: 15 anchors.right: removeButton.left anchors.rightMargin: 10 text:(deviceConnect == "True")? "Disconnect":((btPairable.text == "True")? "Connect":"Pair") // only when HFP or AVP is connected, button will be shown as Disconnect MouseArea { anchors.fill: parent onClicked: { if (currentState == 'discovering'){ request(btAPIpath + 'stop_discovery', function (o) { currentState = "idle" console.log(o.responseText) }) } if (connectButton.text == "Pair"){ connectButton.text = "Connect" request(btAPIpath + 'pair?value=' + deviceAddress, function (o) { btPairable.text = "True" console.log(o.responseText) }) request(btAPIpath + 'set_device_property?Address=' + deviceAddress + '\&Property=Trusted\&value=true', function (o) { console.log(o.responseText) }) } else if (connectButton.text == "Connect"){ connectButton.text = "Disconnect" request(btAPIpath + 'connect?value=' + deviceAddress, function (o) { console.log(o.responseText) }) } else if (connectButton.text == "Disconnect"){ request(btAPIpath + 'disconnect?value=' + deviceAddress, function (o) { console.log(o.responseText) }) connectButton.text = "Connect" } } } } } /* Image { source: '../images/HMI_Settings_DividingLine.svg' anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top anchors.topMargin: -15 visible: model.index > 0 }*/ } } Text { id: pairedlabel width: parent.width anchors.top: parent.top anchors.topMargin: 50 anchors.left: parent.left anchors.leftMargin: 80 height: 80 color:'grey' font.pixelSize: 30 text:{ if(btOn == true && pairedDeviceCount!=0) "LIST OF PAIRED DEVICES" else "" } } ListView{ id: pairedListView width: parent.width anchors.top: pairedlabel.bottom anchors.bottom: pairedlabel.bottom anchors.bottomMargin: (-120*pairedDeviceCount) model: pairedDeviceList delegate: blueToothDevice clip: true } Image { anchors.bottom: pairedListView.bottom anchors.left: parent.left anchors.leftMargin: 80 height: 5 source: (btOn == true && pairedDeviceCount!=0)?'../images/HMI_Settings_DividingLine.svg':'' } Text { id: detectedlabel width: parent.width anchors.top: pairedListView.bottom anchors.topMargin: (pairedDeviceCount!=0)? 80:-80 anchors.left: parent.left anchors.leftMargin: 80 height: 80 color:'grey' font.pixelSize: 30 text: { if (btOn == true) "LIST OF DETECTED DEVICES" else "" } } ListView { id:listView2 width: parent.width anchors.top: detectedlabel.bottom anchors.bottom: parent.bottom anchors.bottomMargin: 150 model: btDeviceList delegate: blueToothDevice clip: true } function checkBluetooth() { request(btAPIpath + 'power', function (o) { // log the json response var msg = JSON.parse(o.responseText) console.log(o.responseText) checked = msg.response.power == "on" }) } function findDevice(address){ for (var i = 0; i < btDeviceList.count; i++) { if (address === btDeviceList.get(i).deviceAddress){ return i } } return -1 } function findPairDevice(address){ for (var i = 0; i < pairedDeviceList.count; i++) { if (address === pairedDeviceList.get(i).deviceAddress){ return i } } return -1 } function updateDeviceAttribute(data){ var text = "" for (var i = 0; i < btDeviceList.count; i++) { if (data.Address === btDeviceList.get(i).deviceAddress){ btDeviceList.get(i).devicePairable = data.Paired if (data.Paired === "True") { //console.log("connectButton " + btDeviceList.get(i).btStatus) //ALCZbtDeviceList.get(i).connectButton.text = "Connect" pairedDeviceList.append({ deviceAddress: btDeviceList.get(i).deviceAddress, deviceName: btDeviceList.get(i).deviceName, devicePairable:btDeviceList.get(i).devicePairable, deviceConnect: btDeviceList.get(i).deviceConnect, connectAVP: btDeviceList.get(i).connectAVP, connectHFP: btDeviceList.get(i).connectHFP, textToShow: "" }) pairedDeviceCount=pairedDeviceCount+1 btDeviceList.remove(i,1) btDeviceList.layoutChanged() } else{ text=deviceConnectionAttribute(data) btDeviceList.set(i, { textToShow: " " + text }) console.log("iamhere" + btDeviceList.get(i).deviceAddress + data.Paired) //btDeviceList.get(i).btStatus = text + btDeviceList.get(i).deviceAddress //btDeviceList.get(i).textToShow btDeviceList.layoutChanged() btDeviceList.get(i).deviceConnect = data.Connected console.log(data.Connected) } } } for (var i = 0; i < pairedDeviceList.count; i++) { if(data.Address === pairedDeviceList.get(i).deviceAddress){ pairedDeviceList.get(i).devicePairable = data.Paired text=deviceConnectionAttribute(data) pairedDeviceList.set(i, { textToShow: " " + text }) // console.log("iamhere" + btDeviceList.get(i).deviceAddress + data.Paired) //btDeviceList.get(i).btStatus = text + btDeviceList.get(i).deviceAddress //btDeviceList.get(i).textToShow pairedDeviceList.layoutChanged() pairedDeviceList.get(i).deviceConnect = data.Connected // console.log(data.Connected) } } } function deviceConnectionAttribute(data){ var text="" if ((data.Paired === "True") && (data.Connected === "True") && (data.AVPConnected === "True") && (data.HFPConnected === "False")) text = "AV Connection, " else if ((data.Paired === "True") && (data.Connected === "True") && (data.HFPConnected === "True") && (data.AVPConnected === "False")) text = "Handsfree Connection, " else if ((data.Paired === "True") && (data.Connected === "True") && (data.HFPConnected === "True") && (data.AVPConnected === "True")) { console.log("all connected!!") text = ", Handsfree & AV Connection"} else text = "" return text } function initBTlist(){ pairedDeviceCount=0 request(btAPIpath + 'discovery_result', function (o) { // log the json response console.log(o.responseText) // translate response into object var jsonObject = eval('(' + o.responseText + ')') jsonObjectBT = eval('(' + JSON.stringify( jsonObject.response) + ')') console.log("BT list refreshed") //console.log(jsonObject.response) for (var i = 0; i < jsonObjectBT.length; i++) { initDevice = 'Y' console.log(jsonObjectBT[i].Paired) if(jsonObjectBT[i].Paired==="True"){ pairedDeviceList.append({ deviceAddress: jsonObjectBT[i].Address, deviceName: jsonObjectBT[i].Name, devicePairable:jsonObjectBT[i].Paired, deviceConnect: jsonObjectBT[i].Connected, connectAVP: jsonObjectBT[i].AVPConnected, connectHFP: jsonObjectBT[i].HFPConnected, textToShow: "" }) pairedDeviceCount=pairedDeviceCount+1 } else btDeviceList.append({ deviceAddress: jsonObjectBT[i].Address, deviceName: jsonObjectBT[i].Name, devicePairable:jsonObjectBT[i].Paired, deviceConnect: jsonObjectBT[i].Connected, connectAVP: jsonObjectBT[i].AVPConnected, connectHFP: jsonObjectBT[i].HFPConnected, textToShow: "" }) } }) } }