Commit 4b6210dd authored by Administrator's avatar Administrator

历史记录采用influxdb

parent 707f3eb7
...@@ -49,3 +49,9 @@ MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" ...@@ -49,3 +49,9 @@ MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
MIX_BASE_API="${BASE_API}" MIX_BASE_API="${BASE_API}"
MIX_LARAVUE_PATH="${LARAVUE_PATH}" MIX_LARAVUE_PATH="${LARAVUE_PATH}"
INFLUX_USERNAME=admin
INFLUX_HOST=127.0.0.1
INFLUX_PASSWORD=null
INFLUX_PORT=8086
INFLUX_DB=zehongcloud
...@@ -8,6 +8,7 @@ use Illuminate\Http\Request; ...@@ -8,6 +8,7 @@ use Illuminate\Http\Request;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Redis; use Illuminate\Support\Facades\Redis;
use App\Http\Controllers\DevicesController; use App\Http\Controllers\DevicesController;
use Illuminate\Support\Facades\Config;
class SwooleCommandMeTcpController extends Controller class SwooleCommandMeTcpController extends Controller
{ {
...@@ -25,6 +26,7 @@ class SwooleCommandMeTcpController extends Controller ...@@ -25,6 +26,7 @@ class SwooleCommandMeTcpController extends Controller
Redis::set('sbjc:' . $datadevice[0], $data); Redis::set('sbjc:' . $datadevice[0], $data);
} }
Redis::lpush('police',$data); Redis::lpush('police',$data);
$this->saveInfluxDb($data);
$this->police(); $this->police();
} }
$dalen = Redis::llen('Devicesdata');//返回队列长度 $dalen = Redis::llen('Devicesdata');//返回队列长度
...@@ -138,4 +140,43 @@ class SwooleCommandMeTcpController extends Controller ...@@ -138,4 +140,43 @@ class SwooleCommandMeTcpController extends Controller
->update(['devicepolice' => $davicedata[1], 'nd' => $davicedata[2]]); ->update(['devicepolice' => $davicedata[1], 'nd' => $davicedata[2]]);
} }
} }
}
\ No newline at end of file /**
* 保存到时序数据库influxdb
* @param $data
* @throws \InfluxDB\Database\Exception
* @throws \InfluxDB\Exception
*/
private function saveInfluxDb($data)
{
$data_array = explode('/', $data);
$device_num = $data_array[0];
$device_status = $data_array[1];
$device_value = $data_array[2];
$influxDb = Config::get('database.influxdb');
$host = $influxDb['default']['host'];
$port = $influxDb['default']['port'];
$username = $influxDb['default']['username'];
$password = $influxDb['default']['password'];
$client = new \InfluxDB\Client($host, $port, $username, $password);
$database = $client->selectDB($influxDb['default']['database']);
$user_id = DB::table('device')->where('devicenum', $device_num)->value('uid');
if($user_id) {
$points = [
new \InfluxDB\Point(
'devices',
$device_value,
['device_num' => $device_num, 'device_status' => $device_status, 'user_id' => $user_id],
[],
time()
),
];
$database->writePoints($points, \InfluxDB\Database::PRECISION_SECONDS);
}
}
}
...@@ -11,6 +11,7 @@ use Illuminate\Http\Request; ...@@ -11,6 +11,7 @@ use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection; use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redis; use Illuminate\Support\Facades\Redis;
...@@ -353,8 +354,20 @@ class DevicesController extends Controller ...@@ -353,8 +354,20 @@ class DevicesController extends Controller
//历史数据查询 //历史数据查询
public function detedevice(Request $request) public function detedevice(Request $request)
{ {
$dete = $request->input('dete'); $request = $request->input();
$devicetime = $this->devicetime($dete); $time_start = $time_stop = false;
if(!is_null($request['timeRange'])) {
$time_start = strtotime($request['timeRange'][0]);
$time_stop = strtotime($request['timeRange'][1]);
}
$devicetime = $this->getDeviceData(
$time_start,
$time_stop,
$request['deviceNum'],
$request['deviceStatus'],
$request['pageSize'],
$request['currentPage']
);
if ($devicetime != 105) { if ($devicetime != 105) {
return $this->jsonSuccessData($devicetime); return $this->jsonSuccessData($devicetime);
} else { } else {
...@@ -603,4 +616,70 @@ class DevicesController extends Controller ...@@ -603,4 +616,70 @@ class DevicesController extends Controller
return 105; return 105;
} }
} }
/**
* 获取历史数据
* @param int $time_start
* @param int $time_stop
* @param string $device_num
* @param int $device_status
* @return array
* @throws \Exception
*/
private function getDeviceData($time_start = false, $time_stop = false, $device_num = '', $device_status = 0, $size=0, $page=0)
{
$influxDb = Config::get('database.influxdb');
$host = $influxDb['default']['host'];
$port = $influxDb['default']['port'];
$username = $influxDb['default']['username'];
$password = $influxDb['default']['password'];
$client = new \InfluxDB\Client($host, $port, $username, $password);
$database = $client->selectDB($influxDb['default']['database']);
$tdatabase = $client->selectDB($influxDb['default']['database']);
$builde = $database->getQueryBuilder();
$tbuilde = $tdatabase->getQueryBuilder();
$result = [];
if($time_start === false) {
$time_start = 0;
}
if($time_stop === false) {
$time_stop = time();
}
$time_start -= 8 * 3600;
$time_stop -= 8 * 3600;
$result = $builde->select('*')
->from('devices')
->setTimeRange($time_start, $time_stop);
$tresult = $tbuilde->select('*')
->from('devices')
->setTimeRange($time_start, $time_stop);
if(!empty($device_num)) {
$where = ["device_num='{$device_num}'"];
$result = $result->where($where);
$tresult = $tresult->where($where);
}
if($device_status != 0 && $device_status != null) {
$where = ["device_status='{$device_status}'"];
$result = $result->where($where);
$tresult = $tresult->where($where);
}
if($this->isadmin() != 1) {
$user_id = Auth::id();
$where = ["user_id='{$user_id}'"];
$result = $result->where($where);
$tresult = $tresult->where($where);
}
$total = $tresult->count('value')->getResultSet()->getPoints();
if(count($total) > 0) {
$result = $result->orderBy('time','DESC')
->limit($size)->offset(($page-1)*$size)
->getResultSet()->getPoints();
} else {
$result = [];
}
return ['list' => $result, 'total' => isset($total[0]) ? $total[0]['count'] : 0];
}
} }
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
"php": "^7.2", "php": "^7.2",
"emadadly/laravel-uuid": "^1.3", "emadadly/laravel-uuid": "^1.3",
"fideloper/proxy": "^4.0", "fideloper/proxy": "^4.0",
"influxdb/influxdb-php": "^1.15",
"laravel/framework": "^7.0", "laravel/framework": "^7.0",
"laravel/passport": "^8.4", "laravel/passport": "^8.4",
"laravel/tinker": "^2.0", "laravel/tinker": "^2.0",
......
{ {
"_readme": [ "_readme": [
"This file locks the dependencies of your project to a known state", "This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "2afb5db88798cc6ab2d4e8a7e00b3b73", "content-hash": "3f4372197e40ba5bc91e08d835604a05",
"packages": [ "packages": [
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
...@@ -831,6 +831,67 @@ ...@@ -831,6 +831,67 @@
], ],
"time": "2019-07-01T23:21:34+00:00" "time": "2019-07-01T23:21:34+00:00"
}, },
{
"name": "influxdb/influxdb-php",
"version": "1.15.0",
"source": {
"type": "git",
"url": "https://github.com/influxdata/influxdb-php.git",
"reference": "bf3415f81962e1ab8c939bc1a08a85f500bead35"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/influxdata/influxdb-php/zipball/bf3415f81962e1ab8c939bc1a08a85f500bead35",
"reference": "bf3415f81962e1ab8c939bc1a08a85f500bead35",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6.0",
"php": "^5.5 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7"
},
"suggest": {
"ext-curl": "Curl extension, needed for Curl driver",
"stefanotorresi/influxdb-php-async": "An asyncronous client for InfluxDB, implemented via ReactPHP."
},
"type": "library",
"autoload": {
"psr-4": {
"InfluxDB\\": "src/InfluxDB"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gianluca Arbezzano",
"email": "gianarb92@gmail.com"
},
{
"name": "Daniel Martinez",
"email": "danimartcas@hotmail.com"
},
{
"name": "Stephen Hoogendijk",
"email": "stephen@tca0.nl"
}
],
"description": "InfluxDB client library for PHP",
"keywords": [
"client",
"influxdata",
"influxdb",
"influxdb class",
"influxdb client",
"influxdb library",
"time series"
],
"time": "2019-05-30T00:15:14+00:00"
},
{ {
"name": "laminas/laminas-diactoros", "name": "laminas/laminas-diactoros",
"version": "2.2.3", "version": "2.2.3",
......
...@@ -156,4 +156,19 @@ return [ ...@@ -156,4 +156,19 @@ return [
], ],
/**
* 时序数据库
*/
'influxdb' => [
'default' => [
'username' => env('INFLUX_USERNAME', 'admin'),
'host' => env('INFLUX_HOST', '127.0.0.1'),
'password' => env('INFLUX_PASSWORD', null),
'port' => env('INFLUX_PORT', 8086),
'database' => env('INFLUX_DB', 'influx_default'),
],
],
]; ];
...@@ -78,10 +78,11 @@ export function equipment() { ...@@ -78,10 +78,11 @@ export function equipment() {
}); });
} }
export function detedevice(dete) { export function detedevice(data) {
return request({ return request({
url: '/devices/detedevice?dete=' + dete, url: '/devices/detedevice',
method: 'get', method: 'post',
data,
}); });
} }
......
<template> <template>
<div class="app-container"> <div class="app-container">
<div class="filter-container"> <div class="filter-container">
<el-date-picker v-model="value2" align="right" type="date" placeholder="选择日期" :picker-options="pickerOptions" value-format="yyyy-MM-dd" @change="dataSearch"></el-date-picker> <el-form :inline="true" :model="formSearch" class="demo-form-inline">
<el-form-item label="设备编号">
<el-input v-model="formSearch.deviceNum" placeholder="输入完整设备编号"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-select
v-model="formSearch.deviceStatus"
style="margin-left: 20px;"
placeholder="请选择"
>
<el-option
v-for="item in optionStatus"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="时间">
<el-date-picker
v-model="formSearch.timeRange"
align="right"
type="datetimerange"
:picker-options="pickerOptions"
range-separator="至"
value-format="yyyy/MM/dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
</div> </div>
<el-pagination
:current-page="formSearch.currentPage"
:page-sizes="[20, 80, 150, 300]"
:page-size="formSearch.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="formSearch.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
</el-pagination>
<el-table :key="tableKey" :data="equipment" border fit highlight-current-rows> <el-table :key="tableKey" :data="equipment" border fit highlight-current-rows>
<el-table-column label="设备编号" width="169"> <el-table-column label="设备编号" width="209">
<template slot-scope="scope"> <template slot-scope="scope">
<span @click="handleCopy(scope.row.devicenum,$event)">{{ scope.row.devicenum }}</span> <span @click="handleCopy(scope.row.device_num,$event)">{{ scope.row.device_num }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="设备名称" width="140"> <el-table-column label="用户ID" width="140">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.username }}</span> <span>{{ scope.row.user_id }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="设备备注" width="140"> <el-table-column label="" width="140">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.deviceremark }}</span> <span>{{ scope.row.value }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="设备联系人" width="140"> <el-table-column label="状态值" width="130">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.devicelinkman }}</span> <span>{{ scope.row.device_status }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="设备手机号" width="140"> <el-table-column label="设备状态" width="130">
<template slot-scope="scope">
<span @click="handleCopy(scope.row.devicephone,$event)">{{ scope.row.devicephone }}</span>
</template>
</el-table-column>
<el-table-column label="设备详情">
<template slot-scope="scope">
<span>{{ scope.row.deviceinfo }}</span>
</template>
</el-table-column>
<el-table-column label="设备分类" width="140">
<template slot-scope="scope">
<span>{{ scope.row.tname }}</span>
</template>
</el-table-column>
<el-table-column label="设备介质" width="130">
<template slot-scope="scope">
<span>{{ scope.row.gas }}</span>
</template>
</el-table-column>
<el-table-column label="设备单位" width="130">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.danwei }}</span> <span>
<el-tag :type=" scope.row.device_status==1 ? 'success' : 'warning' " effect="dark">{{ scope.row.device_status==1 ? '正常' : '异常' }}</el-tag>
</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="设备状态" width="130"> <el-table-column label="时间">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.status_name }}</span> <span>{{ scope.row.time | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -62,13 +88,73 @@ ...@@ -62,13 +88,73 @@
</template> </template>
<script> <script>
import { equipment, detedevice } from '@/api/device'; import { detedevice } from '@/api/device';
import clip from '@/utils/clipboard'; import clip from '@/utils/clipboard';
import BackToTop from '@/components/BackToTop'; import BackToTop from '@/components/BackToTop';
export default { export default {
components: { BackToTop }, components: { BackToTop },
data() { data() {
return { return {
formSearch: {
deviceNum: '',
deviceStatus: 0,
timeRange: null,
pageSize: 20,
currentPage: 1,
total: 0,
},
optionStatus: [{
value: 0,
label: '全部',
}, {
value: 1,
label: '正常',
}, {
value: 2,
label: '错误',
}, {
value: 3,
label: '传感器故障',
}, {
value: 4,
label: '报警',
}, {
value: 5,
label: '低报',
}, {
value: 6,
label: '高报',
}, {
value: 7,
label: '通信故障',
}, {
value: 8,
label: '超量程',
}, {
value: 9,
label: '离线',
}, {
value: 10,
label: '电量低',
}, {
value: 11,
label: '主电故障',
}, {
value: 12,
label: '备电故障',
}, {
value: 13,
label: '无此节点',
}, {
value: 14,
label: '低电压',
}, {
value: 15,
label: '故障',
}, {
value: 16,
label: '报警联动',
}],
equipment: [], equipment: [],
timer: null, timer: null,
tableKey: 0, tableKey: 0,
...@@ -78,25 +164,15 @@ export default { ...@@ -78,25 +164,15 @@ export default {
return time.getTime() > Date.now(); return time.getTime() > Date.now();
}, },
shortcuts: [{ shortcuts: [{
text: '今天', text: '24小时内',
onClick(picker) {
picker.$emit('pick', new Date());
},
}, {
text: '昨天',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
picker.$emit('pick', date);
},
}, {
text: '一周前',
onClick(picker) { onClick(picker) {
const date = new Date(); const end = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); const start = new Date();
picker.$emit('pick', date); start.setTime(start.getTime() - 3600 * 1000 * 24);
picker.$emit('pick', [start, end]);
}, },
}], },
],
}, },
myBackToTopStyle: { myBackToTopStyle: {
right: '50px', right: '50px',
...@@ -110,40 +186,30 @@ export default { ...@@ -110,40 +186,30 @@ export default {
}; };
}, },
created() { created() {
this.equipmentlist(); // 列表 this.dataSearch();
}, },
methods: { methods: {
equipmentlist() { handleSizeChange(val) {
equipment() this.formSearch.pageSize = val;
.then(response => { this.dataSearch();
if (response.code === 200) { },
this.equipment = response.data; handleCurrentChange(val) {
this.timers(); this.formSearch.currentPage = val;
} else if (response.code === 105) { this.dataSearch();
this.$message({
message: response.msg,
type: 'warning',
});
} else {
this.$notify({
title: '警告',
message: 'TCP链接失败',
type: 'warning',
});
}
})
.catch(err => {
console.log(err);
});
}, },
handleCopy(text, event) { handleCopy(text, event) {
clip(text, event); clip(text, event);
}, },
onSubmit() {
this.formSearch.currentPage = 1;
this.dataSearch();
},
dataSearch() { dataSearch() {
detedevice(this.value2) detedevice(this.formSearch)
.then(response => { .then(response => {
if (response.code === 200) { if (response.code === 200) {
this.equipment = response.data; this.equipment = response.data.list;
this.formSearch.total = response.data.total;
} else if (response.code === 105) { } else if (response.code === 105) {
this.$message({ this.$message({
message: response.msg, message: response.msg,
......
...@@ -95,7 +95,7 @@ Route::group(['middleware'=>'auth:api'],function (){ ...@@ -95,7 +95,7 @@ Route::group(['middleware'=>'auth:api'],function (){
Route::get('devices/deviceBasketList','DevicesController@deviceBasketList');//返回禁用设备和废纸篓设备 Route::get('devices/deviceBasketList','DevicesController@deviceBasketList');//返回禁用设备和废纸篓设备
Route::get('devices/addClassify/{data}','DevicesController@addClassify');//添加分类 Route::get('devices/addClassify/{data}','DevicesController@addClassify');//添加分类
Route::get('devices/delteClassify/{id}','DevicesController@delteClassify');//删除分类 Route::get('devices/delteClassify/{id}','DevicesController@delteClassify');//删除分类
Route::get('devices/detedevice','DevicesController@detedevice');//查看历史数据 Route::post('devices/detedevice','DevicesController@detedevice');//查看历史数据
Route::get('devices/addUserDevice','DevicesController@addUserDevice');//返回正常用户 Route::get('devices/addUserDevice','DevicesController@addUserDevice');//返回正常用户
Route::get('devices/control','DevicesController@control');//返回消防监测 Route::get('devices/control','DevicesController@control');//返回消防监测
Route::get('devices/deviceLocation','DevicesController@deviceLocation');//返回设备安装位置 Route::get('devices/deviceLocation','DevicesController@deviceLocation');//返回设备安装位置
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment