存档六月 2019

cisco wap121 reset

接通电源,使用电源适配器,或者POE供电。电源灯,wifi及以太网指示灯全亮。

此时,使用笔尖摁住 reset。这里有2个步骤:

(1)上述指示灯全灭。这时不要松开,继续摁住reset。

(2)电源灯亮起,此时松开reset钮。

复位以后,wap121默认IP是 192.168.1.245

使用Chrome浏览器,在地址栏中键入192.168.1.245,即可出现登录界面。

用户名密码均为 cisco

注意,若不能打开web页面,则是wap121尚未启动完成,需要等一会儿。此时,可以ping通它。

若复位成功,则在cmd下,是可以ping通192.168.1.245,因为wap121不提供DHCP服务,需要将电脑的以太网卡设置为192.168.1.2。

复位后登录,会有设置向导

ubuntu Ubuntu 18.04下,PHP安装curl和xml

WP Statistics 插件,若需要php启用goIP功能,显示访问者的国家和地区,需要有curl模块。

NextGEN Gallery,上传图片,需要启用php-XML模块。

sudo apt-get install php7.2-curl

php7.X 根据版本号修改。

php -v

可以查阅。

sudo apt install php-xml

最后,一块儿重启apache服务。

sudo /etc/init.d/apache2 restart
install php-xm
install curl
restart apache

QWindowsWindow::setGeometry: Unable to set geometry

使用basler相机做一个轮毂形状变动识别。

Debug: File:(c:\users\ysp\source\repos\camera\camera\mycamera.cpp) Line:(63) Function: void __cdecl MyCamera::setup(void) Basler acA640-120gm#00305323AD86#192.168.2.20:3956 
 (2019-06-21 11:02:41)

Critical: File:() Line:(0) Function:  QWindowsWindow::setGeometry: Unable to set geometry 1396x900+200+80 on QWidgetWindow/'cameraClassWindow'. Resulting geometry:  1396x899+200+80 (frame: 8, 31, 8, 8, custom margin: 0, 0, 0, 0, minimum size: 1396x899, maximum size: 16777215x16777215). (2019-06-21 11:21:45)

使用layout布局

宽度/高度值,在此处拿到。

从相机拿到的图像,做resize,仍然会导致界面自动变大,报上述错误。

这里图像,cols(宽)大于rows(高)。

	// 缩放
	int w = img_0.widht();
	int h = img_0.height();
	int w_mat = mat.cols*h / mat.rows;

	cv::resize(mat, mat, cv::Size(w_mat, h));
	if (w_mat > w)
		mat = mat(cv::Rect(0, 0, w, h));

仍然会报错。

可能,lable的宽度,随时变化,慢慢变大。

读取标签宽度,放到resize事件里面,并设置标签的最小尺寸。

// 图像label最小尺寸
ui.image_0->setMinimumSize(QSize(586, 309));
ui.image_1->setMinimumSize(QSize(586, 309));

设置最小尺寸,放在构造函数里。

/* 在label中显示图像: Mat */
void Camera::show_image(QLabel *img, const cv::Mat &src)
{
// 图像数据转换
QImage::Format fmt = QImage::Format_RGB888;
if (src.channels() == 1) {
fmt = QImage::Format_Grayscale8;
}

void Camera::show_image(QLabel *img, const cv::Mat &src)
{
	// 图像数据转换
	QImage::Format fmt = QImage::Format_RGB888;
	if (src.channels() == 1) {
		fmt = QImage::Format_Grayscale8;
	}

	QImage q_image;
	cv::Mat mat = src.clone();

	// 缩放
	int w = this->label_w;
	int h = this->label_h;
	int w_mat = mat.cols*h / mat.rows;

	cv::resize(mat, mat, cv::Size(w_mat, h));
	if (w_mat > w)
		mat = mat(cv::Rect(0, 0, w, h));

	q_image = QImage((const unsigned char*)(mat.data), mat.cols, mat.rows, mat.step, fmt);

	if (q_image.isNull()) {
		qDebug() << QString("show_image(QLabel *img, cv::Mat &mat), convert failed") << endl;
	}

	// 2019.06.21
	QPixmap pix = QPixmap::fromImage(q_image);


	// 避免图像宽度溢出
	//pix = pix.scaled(w, h, Qt::KeepAspectRatioByExpanding);

	img->setAlignment(Qt::AlignCenter);
	img->setPixmap(pix);
}

重载resizeEvent函数。

/*尺寸变动事件*/
void Camera::resizeEvent(QResizeEvent* event) {
	QMainWindow::resizeEvent(event);

	// 图像label

	int w0 = ui.image_0->width();
	int h0 = ui.image_0->height();
	int w1 = ui.image_1->width();
	int h1 = ui.image_1->height();

	this->label_w = w0 < w1 ? w0 : w1;
	this->label_h = h0 < h1 ? h0 : h1;

}
protected:
	 void resizeEvent(QResizeEvent *event) override;

basler相机图像降维

basler 1400万像素相机,分辨率4608*3288 。彩色一个像素3个字节,一幅图像42兆字节。

使用1G bit以太网采集,1秒最大12.5兆字节传输。传递1张照片至少需要3.36秒。

图像获取后,需要resize后,使用opencv进行图像处理、分割,ezsift识别特征。

太大的图像,导致实时性不好。 需要减少 采集时间。

水平,垂直:DecimationHorizontal,DecimationVertical
// 打开相机
CBaslerGigEInstantCamera   *camera = nullptr;
camera->Open();
// 降低采样
camera->DecimationHorizontal.SetValue(factor);
camera->DecimationVertical.SetValue(factor);
// 关闭相机
camera->Close();

因数选2,则图像尺寸缩小2倍。

windows 10, rabbitmq 不能启动

服务启动后,一会儿就停止

查看日志,在运行里,贴入 %APPDATA%\RabbitMQ\

%APPDATA%\RabbitMQ\

日志中,错误如下:

Error description:
    init:do_boot/3 line 817
    init:start_em/1 line 1109
    rabbit:start_it/1 line 478
    rabbit:broker_start/0 line 354
    rabbit:start_apps/2 line 572
    app_utils:manage_applications/6 line 126
    lists:foldl/3 line 1263
    rabbit:'-handle_app_error/1-fun-0-'/3 line 693
throw:{could_not_start,rabbitmq_mqtt,
       {rabbitmq_mqtt,
        {{shutdown,
          {failed_to_start_child,'rabbit_mqtt_listener_sup_:::1883',
           {shutdown,
            {failed_to_start_child,
             {ranch_listener_sup,{acceptor,{0,0,0,0,0,0,0,0},1883}},
             {shutdown,
              {failed_to_start_child,ranch_acceptors_sup,
               {listen_error,
                {acceptor,{0,0,0,0,0,0,0,0},1883},
                eaddrinuse}}}}}}},
         {rabbit_mqtt,start,[normal,[]]}}}}
Log file(s) (may contain more information):
   C:/Users/ysp/AppData/Roaming/RabbitMQ/log/RABBIT~1.LOG
   C:/Users/ysp/AppData/Roaming/RabbitMQ/log/rabbit@DESKTOP-JUT8UPP_upgrade.log
2019-06-23 20:44:02.974 [info] <0.8.0> Log file opened with Lager

原因:1883 被占用。

Qt控制4进4出串口继电器

4路输入/输出,开关量,支持modbus rtu的还好。遇到自定义协议的,就有点麻烦。

232转串口继电器,4进4出串口控制器,。。。

qt的串口类,使用异步方式,需要考虑写、读同步。因为要不停的轮询这个控制器。而且,电脑的USB转串口,选择了便宜的PL2303,速度、掉包、错误,。。。

串口控制器:空闲状态
串口控制器: 输入
串口控制器: 输出

前2个字节,是标识,第3字节是输出,第4字节是输入,第5字节是CRC(前4字节的和与256的余数)

参考QT官方例子,选用线程堵塞方式。(C#,VB串口通讯各种方便。。。)

以下代码,测试成功, QT5.12,VS2017,Win10家庭版。

SerialThread.h

#pragma once

#include <QMutex>
#include <QThread>
#include <QWaitCondition>
#include <QSerialPort>
#include <QQueue>


class SerialThread : public QThread {

	Q_OBJECT

public:
	explicit SerialThread(QObject *parent = nullptr);
	~SerialThread();

	void transaction(const QString &request);
	void m_start();
	void m_stop();


private:
	void run() override;

	QString m_request;
	int _waitTimeout = 0;
	QMutex m_mutex;
	QWaitCondition m_cond;
	bool m_quit = false;

	//QSerialPort _serialport;
	QQueue<QString> queue_cmd;  // 命令队列

	// x0
	bool x0_prev = false;

	void init();


signals:
	void error(const QString);

signals:
	void timeout(const QString);

signals:
	void triger();

signals:
	void x0(bool);
};

SerialThread.cpp

#include "SerialThread.h"

#include <QTime>
#include <QSettings>
#include <QDebug>

SerialThread::SerialThread(QObject *parent) :
	QThread(parent) {

}


SerialThread::~SerialThread() {

	m_mutex.lock();
	m_quit = true;
	m_cond.wakeOne();
	m_mutex.unlock();
	wait();

}

void SerialThread::transaction(const QString &request)
{
	const QMutexLocker locker(&m_mutex);

	//m_request = request;
	queue_cmd.enqueue(request);

	m_cond.wakeOne();
}

/*启动*/
void SerialThread::m_start() {
	if (!isRunning())
		start();
}

/*停止*/
void SerialThread::m_stop()
{
	m_quit = true;
}

void SerialThread::run()
{
	// 串口初始化
	QSerialPort _serialport;
	QSettings settings("./config.ini", QSettings::IniFormat);
	QString port = settings.value("/serial/port", "COM5").toString();
	_waitTimeout = settings.value("/serial/timeout", 25).toUInt();

	_serialport.setPortName(port);
	_serialport.setBaudRate(QSerialPort::Baud9600);
	_serialport.setParity(QSerialPort::NoParity);     //校验:无
	_serialport.setDataBits(QSerialPort::Data8);      //数据位:8
	_serialport.setStopBits(QSerialPort::OneStop);    //停止位:1
	_serialport.setFlowControl(QSerialPort::NoFlowControl);     //流控制:无
	bool serialport_opened = _serialport.open(QIODevice::ReadWrite);
	if (!serialport_opened) {
		QString err = QString("Can't open %1, error code %2").arg(port).arg(_serialport.errorString());
		emit error(err);
		qDebug() << err << endl;
		return;
	}
	
	// 互锁
	m_mutex.lock();

	int currentWaitTimeout = _waitTimeout;
	QString currentRequest;
	m_mutex.unlock();

	// 循环
	while (!m_quit) {
		if (queue_cmd.isEmpty()) {
			currentRequest = QString("5504000059");
		}
		else {
			QString q = queue_cmd.dequeue();
			currentRequest = q;
		}
		// 写请求
		const QByteArray requestData = QByteArray::fromHex(currentRequest.toUtf8());
		// 写数据
		_serialport.write(requestData);
		if (_serialport.waitForBytesWritten(_waitTimeout)) {
			// 读请求
			if (_serialport.waitForReadyRead(currentWaitTimeout)) {
				QByteArray responseData= _serialport.readAll();
				// 读数据
				while (_serialport.waitForReadyRead(10))
					responseData.append(_serialport.readAll());

				//emit error(QString(responseData.toHex()));

				if (responseData.size() == 5) {				
					
					// 输入X0判断
					// crc, 前4个值和,求与256的模
					quint8 sum = responseData[0] + responseData[1] + responseData[2] + responseData[3];
					quint8 crc = sum % 256;
					bool crc_ok = (responseData.at(4) == crc);
					if (crc_ok) {
						// echo
						emit error(QString(responseData.toHex()));

						char x = responseData.at(3);
						char _x = (x & 1);
						bool x0 = !(x & 1);
						// 0 ---> 1上升沿, 无忽略
						if (!x0_prev && x0) {
							// 触发动作
							emit triger();
						}
						x0_prev = x0;
						emit this->x0(x0);
					}
				}
				else {
					//qDebug() << QString("Data read error, %1").arg(QString(responseData.toHex())) << endl;
				}
			}
			else {
				emit timeout(tr("Read timeout %1")
					.arg(QTime::currentTime().toString()));
			}
		}
		else {
			emit timeout(tr("Write timeout %1")
				.arg(QTime::currentTime().toString()));
		}

		m_mutex.lock();
                // 等待解锁信号,最多等50ms或者30ms
		m_cond.wait(&m_mutex, 50);
		currentWaitTimeout = _waitTimeout;
		//currentRequest = m_request;

		m_mutex.unlock();
	}

}

/*串口初始化*/
void SerialThread::init() {

	
}

经过跟踪发现,串口控制器与PL2303的配合,经常出现最后一个字节不连贯,要么读出4个字节,要么读出6个字节。

USB转串口,还是FT232之类要好。

QByteArray与modbus命令串

modbus通讯命令,使用16进制。

QString a("5504000059");
QByteArray b = QByteArray::fromHex(a.toUtf8());

通常写字符串比较方便。

QByteArray b = QByteArray::fromHex("5504000059");

fromHex直接转换字符串。

Couldn’t access RabbitMQ web interface

Couldn’t access RabbitMQ web interface from http://127.0.0.1:15672

在windows下,按装RabbitMQ,rabbitmq-server-3.7.15.exe 。安装结束后,在服务里启动它。

RabbitMQ服务支持win10 x64,emqqtd 2.X只能跑控制台

但是服务启动以后,http://127.0.0.1:15672不能打开管理页面。

rabbitmq-plugins enable rabbitmq_management

额外,需要启用管理插件。

用户名/密码,默认是guest