RK3566添加湿度传感器以及浅析hal层

news2025/2/28 5:43:00

RK3566添加一款温湿度传感器gxht3x.挂在i2c总线下。驱动部分就不多做解析。大致流程硬件接好i2c线以及vcc gnd。后看数据手册。初始化寄存器,然后要读数据的话读那个寄存器,读出来的数据要做一个转化,然后实现open read write ioctl函数就行了。本文主要讲解hal层 。直接贴驱动代码。

/* drivers/input/sensors/temperature/tmp_ms5607.c
 *
 * Copyright (C) 2012-2015 ROCKCHIP.
 * Author: luowei <lw@rock-chips.com>
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/uaccess.h>

#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>
#include <asm/atomic.h>
#include <linux/delay.h>
#include <linux/freezer.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include <linux/sensor-dev.h>


static int sensor_active(struct i2c_client *client, int enable, int rate)
{
	int result = 0;
	return result;
}



static int sensor_init(struct i2c_client *client)
{
	int result = 0;
	return result;
}


static int sensor_i2c_write(struct i2c_client *client,
			    unsigned int len, unsigned char const *data)
{
	struct i2c_msg msgs[1];
	int res;

	msgs[0].addr = 0x44;
	msgs[0].flags = 0;	/* write */
	msgs[0].buf = (unsigned char *)data;
	msgs[0].len = len;

	res = i2c_transfer(client->adapter, msgs, 1);
	printk("wzf---i2c_transfer count = %d\n", res);
	return res;

}

static int senosr_i2c_read(struct i2c_client *client,
			   unsigned int len, unsigned char *data)
{
	struct i2c_msg msgs[1];
	int res;
	printk("wzf:-----addr = %x-----\n",(int)client->addr);
	msgs[0].addr = 0x44;
	msgs[0].flags = I2C_M_RD;
	msgs[0].buf = data;
	msgs[0].len = len;

	res = i2c_transfer(client->adapter, msgs, 1);
	printk("wzf---i2c_transfer count = %d\n", res);
	return res;

}

static int humidity_report_value(struct input_dev *input, int data)
{
	//get temperature, high and temperature from register data
	printk("ms5607-----hum report data= %d\n",data);
	input_report_abs(input, ABS_VOLUME, data);
	input_sync(input);
	msleep(100);
	return 0;
}

static int sensor_report_value(struct i2c_client *client)
{
	
    int ret = 0;
	unsigned int tem = 0,hum = 0;
	int Temperature=0,Humidity=0;

	char recvbuffer[6];
	char sendbuffer[2] = {0x2C,0x10};
	struct sensor_private_data *sensor =
	    (struct sensor_private_data *) i2c_get_clientdata(client);
	printk("wzf:--------%s---------\n",__func__);

	memset(recvbuffer, 0, 6);
	ret = sensor_i2c_write(client, 2, sendbuffer);
	if (!ret){
		printk("sensor_i2c_read failed!\n");
		//return -1;
	}
	msleep(2);
	ret = senosr_i2c_read(client, 6, recvbuffer);
	if (!ret){
		printk("sensor_i2c_read failed!\n");
		//return -1;
	}
	printk("read recvbuffer= %s-----\n",recvbuffer);
	tem = ((recvbuffer[0]<<8) | recvbuffer[1]);//温度拼接
	hum = ((recvbuffer[3]<<8) | recvbuffer[4]);//湿度拼接
	printk("wzf:ms5607 hum =%d\n",hum);
	printk("wzf:ms5607 temp =%d\n",tem);
	/*转换实际温度*/
	Temperature= (175* tem/65535-45) ;// T = -45 + 175 * tem / (2^16-1)
	//Temperature =(315*tem/65535-49);
	Humidity= (100* hum/65535);// RH = hum*100 / (2^16-1)
	printk("---Temp : %d  Hum: %d ----\n",Temperature,Humidity);
	//Humidity=950;
	if(!Humidity)
		return 0;
	ret = humidity_report_value(sensor->input_dev, Humidity);
	return 0;
}


struct sensor_operate humidity_gxht3x_ops = {
	.name				= "hum_gxht3x",
	.type				= SENSOR_TYPE_HUMIDITY,	//sensor type and it should be correct
	.id_i2c				= HUMIDITY_ID_GXHT3X,	//i2c id number
	.read_reg			= SENSOR_UNKNOW_DATA,	//read data
	.read_len			= 2,			//data length
	.id_reg				= SENSOR_UNKNOW_DATA,	//read device id from this register
	.id_data 			= SENSOR_UNKNOW_DATA,	//device id
	.precision			= 16,		//8 bits
	.ctrl_reg 			= SENSOR_UNKNOW_DATA,	//enable or disable
	.int_status_reg 		= SENSOR_UNKNOW_DATA,	//intterupt status register
	.range				= {0,65535},		//range
	.trig				= IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
	.active				= sensor_active,
	.init				= sensor_init,
	.report				= sensor_report_value,
};

/****************operate according to sensor chip:end************/
static int humidity_gxht3x_probe(struct i2c_client *client, const struct i2c_device_id *devid)
{
	printk("wzf:----%s----\n",__func__);
	return sensor_register_device(client, NULL, devid, &humidity_gxht3x_ops);
}

static int humidity_gxht3x_remove(struct i2c_client *client)
{
	return sensor_unregister_device(client, NULL, &humidity_gxht3x_ops);
}

static const struct i2c_device_id humidity_gxht3x_id[] = {
	{"hum_gxht3x", HUMIDITY_ID_GXHT3X},
	{}
};

static struct i2c_driver humidity_ms5607_driver = {
	.probe = humidity_gxht3x_probe,
	.remove = humidity_gxht3x_remove,
	.shutdown = sensor_shutdown,
	.id_table = humidity_gxht3x_id,
	.driver = {
		.name = "humidity_gxht3x",
	#ifdef CONFIG_PM
		.pm = &sensor_pm_ops,
	#endif
	},
};

module_i2c_driver(humidity_ms5607_driver);

MODULE_AUTHOR("luowei <lw@rock-chips.com>");
MODULE_DESCRIPTION("ms5607 temperature driver");
MODULE_LICENSE("GPL");

接下来对hal层进行浅析hal对于驱动来说还是要会的。我也不会,在网上找资料找出来的如有错误希望各位大佬能指出。
在这里插入图片描述
在这里插入图片描述
以上资料来自博主~未来可期点击看大佬的文章
总结一下:
对于我们的湿度传感器来说:(kernel 层驱动通过i2c读取寄存器拿到湿度数据) —fileoperation---->(hardware层通过open节点,以及ioctl获取到数据,填充这些结构体.hw_device_t 填充模块ID 名称 描述 版本等信息。hw_moule_ts实现功能函数。等jni层获取到该结构体指针的时候可以调用这些功能函数)------jni-------->(framewark层注册java native interface.java本地接口,以便上层调用)------->apk.
那我们看hal层代码就先从这三个结构体入手。

hardware\libhardware\include\hardware\hardware.h
struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;

/**
 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
 * and the fields of this data structure must begin with hw_module_t
 * followed by module specific information.
 */
typedef struct hw_module_t {
    /** tag must be initialized to HARDWARE_MODULE_TAG */
    uint32_t tag;

    /**
     * The API version of the implemented module. The module owner is
     * responsible for updating the version when a module interface has
     * changed.
     *
     * The derived modules such as gralloc and audio own and manage this field.
     * The module user must interpret the version field to decide whether or
     * not to inter-operate with the supplied module implementation.
     * For example, SurfaceFlinger is responsible for making sure that
     * it knows how to manage different versions of the gralloc-module API,
     * and AudioFlinger must know how to do the same for audio-module API.
     *
     * The module API version should include a major and a minor component.
     * For example, version 1.0 could be represented as 0x0100. This format
     * implies that versions 0x0100-0x01ff are all API-compatible.
     *
     * In the future, libhardware will expose a hw_get_module_version()
     * (or equivalent) function that will take minimum/maximum supported
     * versions as arguments and would be able to reject modules with
     * versions outside of the supplied range.
     */
    uint16_t module_api_version;
#define version_major module_api_version
    /**
     * version_major/version_minor defines are supplied here for temporary
     * source code compatibility. They will be removed in the next version.
     * ALL clients must convert to the new version format.
     */

    /**
     * The API version of the HAL module interface. This is meant to
     * version the hw_module_t, hw_module_methods_t, and hw_device_t
     * structures and definitions.
     *
     * The HAL interface owns this field. Module users/implementations
     * must NOT rely on this value for version information.
     *
     * Presently, 0 is the only valid value.
     */
    uint16_t hal_api_version;
#define version_minor hal_api_version

    /** Identifier of module */
    const char *id;

    /** Name of this module */
    const char *name;

    /** Author/owner/implementor of the module */
    const char *author;

    /** Modules methods */
    struct hw_module_methods_t* methods;

    /** module's dso */
    void* dso;

#ifdef __LP64__
    uint64_t reserved[32-7];
#else
    /** padding to 128 bytes, reserved for future use */
    uint32_t reserved[32-7];
#endif

} hw_module_t;

typedef struct hw_module_methods_t {
    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

} hw_module_methods_t;

/**
 * Every device data structure must begin with hw_device_t
 * followed by module specific public methods and attributes.
 */
typedef struct hw_device_t {
    /** tag must be initialized to HARDWARE_DEVICE_TAG */
    uint32_t tag;

    /**
     * Version of the module-specific device API. This value is used by
     * the derived-module user to manage different device implementations.
     *
     * The module user is responsible for checking the module_api_version
     * and device version fields to ensure that the user is capable of
     * communicating with the specific module implementation.
     *
     * One module can support multiple devices with different versions. This
     * can be useful when a device interface changes in an incompatible way
     * but it is still necessary to support older implementations at the same
     * time. One such example is the Camera 2.0 API.
     *
     * This field is interpreted by the module user and is ignored by the
     * HAL interface itself.
     */
    uint32_t version;

    /** reference to the module this device belongs to */
    struct hw_module_t* module;

    /** padding reserved for future use */
#ifdef __LP64__
    uint64_t reserved[12];
#else
    uint32_t reserved[12];
#endif

    /** Close this device */
    int (*close)(struct hw_device_t* device);

} hw_device_t;

然后我们在看sensor中定义的结构体

\hardware\libhardware\include\hardware\sensors.h
/**
 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
 * and the fields of this data structure must begin with hw_module_t
 * followed by module specific information.
 */
struct sensors_module_t {
    struct hw_module_t common;

    /**
     * Enumerate all available sensors. The list is returned in "list".
     * return number of sensors in the list
     */
    int (*get_sensors_list)(struct sensors_module_t* module,
            struct sensor_t const** list);

    /**
     *  Place the module in a specific mode. The following modes are defined
     *
     *  0 - Normal operation. Default state of the module.
     *  1 - Loopback mode. Data is injected for the supported
     *      sensors by the sensor service in this mode.
     * return 0 on success
     *         -EINVAL if requested mode is not supported
     *         -EPERM if operation is not allowed
     */
    int (*set_operation_mode)(unsigned int mode);
};

/*
 * sensors_poll_device_t is used with SENSORS_DEVICE_API_VERSION_0_1
 * and is present for backward binary and source compatibility.
 * See the Sensors HAL interface section for complete descriptions of the
 * following functions:
 * http://source.android.com/devices/sensors/index.html#hal
 */
struct sensors_poll_device_t {
    struct hw_device_t common;
    int (*activate)(struct sensors_poll_device_t *dev,
            int sensor_handle, int enabled);
    int (*setDelay)(struct sensors_poll_device_t *dev,
            int sensor_handle, int64_t sampling_period_ns);
    int (*poll)(struct sensors_poll_device_t *dev,
            sensors_event_t* data, int count);
};

这里主要定义了俩个结构体 :struct sensors_module_t , 里面包含了 hw_module_t ; 那hw_module_t我们之前说是填充模块信息的包括ID 名称等等。但是它里面还包含了俩个函数 get_sensors_list 这个函数将返回所有可以的传感器列表。set_operation_mode:将模块设置特定模式:0 正常模式 1回环模式。第二个结构体:struct sensors_poll_device_t ,里面包含了struct hw_device_t;struct hw_device_t里面是特定的实现函数,但是我们还要增加我们自己的功能函数activate ,setDelay ,poll。
ok,我查看在libhardware下的头文件定义。接下来看具体的实现。

hardware\rockchip\sensor\st\sensors.c
/*  sensors_module_t 填充hw_module_t的 模块描述 */
 struct sensors_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .version_major = 1,
        .version_minor = 0,
        .id = SENSORS_HARDWARE_MODULE_ID,
        .name = "Rockchip Sensors Module",
        .author = "The RKdroid Project",
        .methods = &sensors_module_methods,
    },
    .get_sensors_list = sensors__get_sensors_list
};
/* hw_module_methods_t 实现open函数  */
static struct hw_module_methods_t sensors_module_methods = {
    .open = open_sensors
};
/* 实现sensor.h中 sensors_module_t结构体中 get_sensors_list函数  */
static int sensors__get_sensors_list(struct sensors_module_t* module,
        struct sensor_t const** list)
{
    *list = sSensorList;
    return ARRAY_SIZE(sSensorList);
}

那么sensors_poll_device_t的几个函数的实现都没有写???这个要看具体设备再具体实现。
直接看湿度传感器hal层结构体定义。

hardware\rockchip\sensor\st\HumiditySensor.h
class HumiditySensor : public SensorBase {
    int mEnabled;
    InputEventCircularReader mInputReader;
    sensors_event_t mPendingEvent;  
    bool mHasPendingEvent;

    
    int setInitialState();

public:
            HumiditySensor();
    virtual ~HumiditySensor();

    virtual int setDelay(int32_t handle, int64_t ns);
    virtual int enable(int32_t handle, int enabled);
    virtual int readEvents(sensors_event_t* data, int count);   
    virtual bool hasPendingEvents() const;
    virtual int isActivated(int handle);
    void processEvent(int code, int value);
};

/*****************************************************************************/

#define HUMIDITY_IOCTL_MAGIC			'h'
#define HUMIDITY_IOCTL_GET_ENABLED	_IOR(HUMIDITY_IOCTL_MAGIC, 1, int *)
#define HUMIDITY_IOCTL_ENABLE			_IOW(HUMIDITY_IOCTL_MAGIC, 2, int *)
#define HUMIDITY_IOCTL_DISABLE		_IOW(HUMIDITY_IOCTL_MAGIC, 3, int *)
#define HUMIDITY_IOCTL_SET_DELAY		_IOW(HUMIDITY_IOCTL_MAGIC, 4, int *)

class HumiditySensor : public SensorBase ; 可以看出class HumiditySensor 继承了SensorBase,那我们看一下class SensorBase

struct sensors_event_t;

class SensorBase {
protected:
    const char* dev_name;
    const char* data_name;
    int         dev_fd;
    int         data_fd;

    static int openInput(const char* inputName);
    static int64_t getTimestamp();
    static int64_t timevalToNano(timeval const& t) {
        return t.tv_sec*1000000000LL + t.tv_usec*1000;
    }

    int open_device();
    int close_device();

public:
            SensorBase(
                    const char* dev_name,
                    const char* data_name);

    virtual ~SensorBase();

    virtual int readEvents(sensors_event_t* data, int count) = 0;
    virtual bool hasPendingEvents() const;
    virtual int getFd() const;
    virtual int setDelay(int32_t handle, int64_t ns);
    virtual int enable(int32_t handle, int enabled) = 0;
    virtual int isActivated(int handle);
};

这里的setdelay isActivated readEvents不就是sensors_poll_device_t里面的功能实现函数。同时在HumiditySensor类里面也实现了这几个函数。查看class HumiditySensor里面成员的实现。

/*
 * Copyright (C) 2010 Motorola, Inc.
 * Copyright (C) 2008 The Android Open Source Project
 *
 * 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.
 */

#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>

#include "HumiditySensor.h"

/*****************************************************************************/

HumiditySensor::HumiditySensor()
    : SensorBase(HUM_DEVICE_NAME, "humidity"),
      mEnabled(0),
      mInputReader(32),
      mHasPendingEvent(false)
{
	LOGD("new class humidity");
    mPendingEvent.version = sizeof(sensors_event_t);
    mPendingEvent.sensor = ID_HUM;
    mPendingEvent.type = SENSOR_TYPE_RELATIVE_HUMIDITY;
    memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));

     open_device();

    int flags = 0;
    if ((dev_fd > 0) && (!ioctl(dev_fd, HUMIDITY_IOCTL_GET_ENABLED, &flags))) {
        if (flags) {
            mEnabled = 1;
            setInitialState();
        }
    }
}

HumiditySensor::~HumiditySensor() {
	LOGD("delete class humidity");
    if (dev_fd > 0) {
        close(dev_fd);
        dev_fd = -1;
    }
}

int HumiditySensor::setInitialState() {
    struct input_absinfo absinfo;
    if ((data_fd > 0) && !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_HUMIDITY), &absinfo)) {
        mHasPendingEvent = true;
        mPendingEvent.relative_humidity = CONVERT_B * absinfo.value;
    }
    return 0;
}

int HumiditySensor::enable(int32_t, int en) {
    int flags = en ? 1 : 0;
    int err = 0;
    if (flags != mEnabled) {
        if (dev_fd < 0) {
            open_device();
        }
        err = ioctl(dev_fd, HUMIDITY_IOCTL_ENABLE, &flags);
        err = err<0 ? -errno : 0;
        LOGE_IF(err, "HUMIDITY_IOCTL_ENABLE failed (%s)", strerror(-err));
        if (!err) {
            mEnabled = en ? 1 : 0;
            if (en) {
                setInitialState();
            }
        }
    }
    return err;
}

bool HumiditySensor::hasPendingEvents() const {
    return mHasPendingEvent;
}


int HumiditySensor::setDelay(int32_t handle, int64_t ns)
{
    if (ns < 0)
        return -EINVAL;
	
    if (dev_fd < 0) {
        open_device();
    }

    int delay = ns / 1000000;
    if (ioctl(dev_fd, HUMIDITY_IOCTL_SET_DELAY, &delay)) {
        return -errno;
    }
    return 0;
}

int HumiditySensor::isActivated(int /* handle */)
{
    return mEnabled;
}

int HumiditySensor::readEvents(sensors_event_t* data, int count)
{
    if (count < 1)
        return -EINVAL;

    if (mHasPendingEvent) {
        mHasPendingEvent = false;
        mPendingEvent.timestamp = getTimestamp();
        *data = mPendingEvent;
        return mEnabled ? 1 : 0;
    }

    ssize_t n = mInputReader.fill(data_fd);
    if (n < 0)
        return n;
    int numEventReceived = 0;
    input_event const* event;

    while (count && mInputReader.readEvent(&event)) {
        int type = event->type;
        if (type == EV_ABS) {
            processEvent(event->code, event->value);
        } else if (type == EV_SYN) {
            int64_t time = timevalToNano(event->time);
            mPendingEvent.timestamp = time;
            if (mEnabled) {
                *data++ = mPendingEvent;
                count--;
                numEventReceived++;
            }
        } else {
            ALOGE("HumiditySensor: unknown event (type=%d, code=%d)",
                    type, event->code);
        }
        mInputReader.next();
    }

    return numEventReceived;
}

void HumiditySensor::processEvent(int code, int value)
{
    if (code == EVENT_TYPE_HUMIDITY) {
            //mPendingEvent.relative_humidity = value * CONVERT_B ;
			mPendingEvent.relative_humidity = value;
			LOGD("HUM---%s:value=%d\n",__FUNCTION__, value);
			LOGD("HUM---%s:value * CONVERT_B = %f\n",__FUNCTION__, mPendingEvent.relative_humidity);
    }
}

里面的核心函数就是open 然后ioctl发送不同的魔数去获取到数据。那么我们的hal层拿到数据只是完成了启下作用,即从内核驱动中获取数据。那么我们还要把数据给到JNI。由于hal层和farmware层都是运行在用户空间,jni也是由C/C++编写。并且hal层是以.so的动态库文件的形式存在。那么我们只要在jni包含该库文件就可以。调用到我们的功能函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/361145.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode】剑指 Offer 10- Ⅲ. 矩形覆盖 p79 -- Java Version

题目链接&#xff1a;无 1. 题目介绍&#xff08;10- Ⅲ. 矩形覆盖 &#xff09; 我们可以用2x1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2x1的小矩形无重叠地覆盖一个2xn的大矩形&#xff0c;总共有多少种方法&#xff1f; 【测试用例】&#xff1a; 示例 1&#xff…

[学习笔记]Rocket.Chat业务数据备份

Rocket.Chat 的业务数据主要存储于mongodb数据库的rocketchat库中&#xff0c;聊天中通过发送文件功能产生的文件储存于/app/uploads中&#xff08;文件方式设置为"FileSystem"&#xff09;&#xff0c;因此在对Rocket.Chat做数据移动或备份主要分为两步&#xff0c;…

JavaScript高级程序设计读书分享之4章——4.2执行上下文与作用域

JavaScript高级程序设计(第4版)读书分享笔记记录 适用于刚入门前端的同志 执行上下文 变量或函数的上下文决定 了它们可以访问哪些数据&#xff0c;以及它们的行为。在浏览器中&#xff0c;全局上下文就是我们常说的 window 对象&#xff08;第 12 章会详细介绍&#xff09;&am…

【技术分享】Web自动化之Selenium安装

Web 应用程序的验收测试常常涉及一些手工任务&#xff0c;例如打开一个浏览器&#xff0c;并执行一个测试用例中所描述的操作。但是手工执行的任务容易出现人为的错误&#xff0c;也比较费时间。因此&#xff0c;将这些任务自动化&#xff0c;就可以消除人为因素。Selenium 可以…

Js中blob、file、FormData、DataView、TypedArray

引言 最开始我们看网页时&#xff0c;对网页的需求不高&#xff0c;显示点文字&#xff0c;显示点图片就很满足了&#xff0c;所以对于浏览器而言其操作的数据其实并不多&#xff08;比如读取本地图片显示出来&#xff0c;或上传图片到服务器&#xff09;&#xff0c;那么浏览器…

网络安全之认识挖矿木马

一、什么是挖矿木马&#xff1f; 比特币是以区块链技术为基础的虚拟加密货币&#xff0c;比特币具有匿名性和难以追踪的特点&#xff0c;经过十余年的发展&#xff0c;已成为网络黑产最爱使用的交易媒介。大多数勒索病毒在加密受害者数据后&#xff0c;会勒索代价高昂的比特币…

GEE学习笔记 六十三:新的地图图层ui.Map.CloudStorageLayer

在GEE中导出数据有一种方式是直接导出地图到Google Cloud Storage中&#xff0c;也就是Export.map.toCloudStorage(xxx)&#xff0c;这种方式是将我们计算生成影像导出成为静态瓦片的格式存放在Google Cloud Storage中。我们可以在其他的前端程序比如OpenLayer、Mapbox GL JS等…

Python开发-学生管理系统

文章目录1、需求分析2、系统设计3、系统开发必备4、主函数设计5、 学生信息维护模块设计6、 查询/统计模块设计7、排序模块设计8、 项目打包1、需求分析 学生管理系统应具备的功能&#xff1a; ●添加学生及成绩信息 ●将学生信息保存到文件中 ●修改和删除学生信息 ●查询学生…

Docker之路(1.Docker概述、组成以及特点)

1.docker为什么会出现&#xff1f; 一款产品或者项目来说&#xff0c;一般有三个环境&#xff0c;日常/测试环境、预发环境、正式/线上环境 这么多环境&#xff0c;对其环境的配置是十分麻烦的&#xff0c;每一个机器都要部署环境&#xff0c;有的会有集群Redis、Hadoop等&…

最全es6数组方法

1.arr.push()从后面添加元素,返回值为添加完后的数组的长度 let arr [1,2,3,4,5] console.log(arr.push(5)) // 6 console.log(arr) // [1,2,3,4,5,5]2.arr.pop()从后面删除元素,只能是一个&#xff0c;返回值是删除的元素 let arr [1,2,3,4,5] console.log(arr.pop())//5 …

学UI设计,可以向哪些方向发展?该怎么学?

1、什么是UI设计&#xff1f;UI设计&#xff0c;全称 User Interface&#xff0c;翻译成中文意思叫做用户界面设计。2、UI设计的类型UI设计按用户和界面来分可分成四种UI设计。分别是移动端UI设计&#xff0c;PC端UI设计&#xff0c;游戏UI设计&#xff0c;以及其它UI设计。第一…

信号量(上)

竞争是协作的特例&#xff0c;竞争关系是属于协作关系 信号量可以解决协作关系存在的问题&#xff0c;那么它也可以解决竞争关系存在的问题 信号量 信号量就是一个整数 先等待&#xff0c;然后再发送信号 p在荷兰语中代表测试 v在荷兰语代表增加 这个函数的执行流需要自己画&a…

C# FFmpeg推流Vlc.DotNet拉流优化参数

FFmpeg是流媒体开源神器&#xff0c;视频转换、剪裁包括推流&#xff0c;无所不能&#xff0c;很多系统都是基于其开发的。拉流可以用FFplay&#xff0c;但是不利于集成到自己的代码中&#xff0c;因此拉流选择了Vlc.DotNet。 在使用中&#xff0c;仅使用默认参数&#xff0c;…

hadoop3.*集群搭建,小白必看

hadoop广义上讲是一个大数据生态圈&#xff0c;接受大量处理、处理大量数据的一个全套的框架&#xff01;hadoop3.x版本以后&#xff0c;主要有三大模块&#xff0c;HDFS、YARN、mapReduce这三大核心组成&#xff01;什么是HDFS?分布式文件系统&#xff0c;hadoop集群的功能类…

Centos7搭建hadoop3.3.4分布式集群

文章目录1、背景2、集群规划2.1 hdfs集群规划2.2 yarn集群规划3、集群搭建步骤3.1 安装JDK3.2 修改主机名和host映射3.3 配置时间同步3.4 关闭防火墙3.5 配置ssh免密登录3.5.1 新建hadoop部署用户3.5.2 配置hadoopdeploy用户到任意一台机器都免密登录3.7 配置hadoop3.7.1 创建目…

IO多路复用

文章目录1 概念2. IO多路复用的出现2.1 阻塞IO2.2 非阻塞IO2.3 IO 多路复用2.3.1 select2.3.2 poll2.3.3 epoll总结1 概念 IO多路复用(IO Multiplexing) 是一种同步IO模型&#xff0c;在单个进程/线程内就可以同时处理多个IO请求。一个进程/线程可以监视多个文件句柄&#xff…

深度 | “人人都是数据分析师”的时代,为什么建议你学好python?

01 潜力巨大的数据分析岗位在信息时代的今天&#xff0c;数据推动业务发展、数据辅助业务决策早已成为大势所向&#xff0c;而顺应大数据时代号召的人&#xff0c;薪资待遇自然也是让人羡慕不已——数据分析师确实是高薪职业&#xff0c;大部分公司提供的待遇基本上是10K往上走…

好消息!Ellab(易来博)官方微信公众号开通了!携虹科提供专业验证和监测解决方案

自1949年以来&#xff0c;丹麦Ellab一直通过全球范围内的验证和监测解决方案&#xff0c;协助全球生命科学和食品公司优化和改进其流程的质量。Ellab全面的无线数据记录仪&#xff0c;热电偶系统&#xff0c;无线环境监测系统&#xff0c;校准设备&#xff0c;软件解决方案等等…

Ae:导入 Photoshop 文件

由于 Ae 内嵌了 Photoshop 的渲染引擎&#xff0c;所以可以识别并导入 Photoshop 文件的所有属性&#xff0c;包括位置、混合模式、不透明度、可见性、透明度&#xff08;Alpha 通道&#xff09;、图层蒙版、图层组、调整图层、图层样式、图层剪切路径、矢量蒙版、图像参考线等…

IPEmotion新增功能:交流电功率分析计算

一 应用背景 随着国内电动汽车行业的快速发展&#xff0c;在相同的道路环境和行驶状态下&#xff0c;增加电动车的整体续航里程和提升乘员对于行驶途中用电需求的满意度尤为重要。因此&#xff0c;需要采集试验过程中交直流电压电流信号&#xff0c;以计算出车辆各种部件输出和…