【多服务场景化解决方案】智能家居(UrbanHome)
介绍
UrbanHome是一款提供房屋维修服务的移动应用。如有维修需求,用户可通过该应用联系所在城市的管道工,电工,保洁,漆匠,木匠,修理工等,或是搜寻导航附近的维修商店。
通过构建UrbanHome这款应用,您可以实现以下华为移动服务的功能:
1. 通过账号服务完成用户验证。
2. 通过云数据库,不同城市的维修者们能够增、删、改、查自己的信息。
3. 通过用户身份服务,用户可以管理多个地址并基于当前地址通过云数据库查看维修者信息。
4. 通过位置服务,定位服务和地图服务,用户可以搜索并导航附近的维修店。
您将建立什么
在这个Codelab中,您将会建立一个集成了账号服务,地图服务、定位服务、位置服务、云数据库和用户身份服务的项目。在该项目中,您可以尝试:
- 使用账号服务实现华为账号登录。
- 使用云数据库管理数据。
- 使用定位服务获取当前位置的坐标并使用地图服务绘制用户前往修理店的路线。
- 使用用户身份服务管理地址。
- 使用位置服务搜索附近修理店。
您将学到什么
在这个Codelab中,您将学到:
- 如何使用账号服务实现华为账号登录。
- 如何使用定位服务获取用户当前位置。
- 如何使用地图服务在HMS地图上定位消费者所在位置。
- 如何使用位置服务获取周边修理店位置。
- 如何使用云数据库为修理者提供信息的增、删、改、查操作。
- 如何使用用户身份服务为用户提供地址的增、删、改、查操作。
您需要什么
说明:需要一个华为帐号,并且此账号身份已验证。
硬件要求
请提前准备上述硬件环境和相关设备。
- 运行Windows 10操作系统的台式机或笔记本电脑。
- 安装HMS Core (APK) 5.1.0.309或以上版本的华为手机一部。
软件要求
请提前准备上述软件环境。
- Android Studio 4.X
- JDK 1.8或以上。
- SDK Platform 28或以上。
- Gradle 4.6或以上。
能力接入准备
要集成HMS Core相关服务,需要完成以下准备:
- 登录AppGallery Connect并创建应用。
- 创建Android Studio工程。
- 生成签名证书。
- 生成签名证书指纹。
- 配置签名证书指纹。
- 添加应用包名并保存配置文件。
- 在项目级build.gradle文件中,添加AppGallery Connect插件以及Maven仓地址。
- 在Android Studio中配置签名证书。
具体操作,请按照HMS Core集成准备中的详细说明来完成。
启用相关服务
前往“项目设置”页面,选择“API管理”并开通下述服务。
说明:部分API默认是关闭的,您必须手动启用。
- 账号服务
- 定位服务
- 位置服务
- 地图服务
至此,您已成功启用应用所需的华为服务。
集成账号服务
通过华为帐号开放服务,Android应用可以方便和安全地实现快速登录授权、读取短信验证码等功能。凭借用户授权凭证(即Access Token),应用可快速调用华为开放接口。
在依赖代码块中添加账号服务SDK的依赖。
implementation 'com.huawei.hms:hwid:5.0.3.301'
使用账号服务实现华为账号登录
1.申请授权,获取Token。
若用户选择使用华为账号登录应用,请调用如下startAuthService()方法启动授权。
/**
* Start AuthService and request the scope parameters
*/
private fun startAuthService() {
HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
.setUid()
.setProfile()
.setMobileNumber()
.setEmail()
.setIdToken()
.setAccessToken()
.setAuthorizationCode()
.setScopeList(scopes)
.createParams()
startActivityForResult(service.signInIntent, AppConstants.LOGIN_AUTH_CODE)
}
2.调用如下回调方法检测用户授权是否成功。
说明:更多详细信息请参考账号服务接入流程。
/**
*Check authentication is successful or not.
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, @Nullable data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK)
when (requestCode) {
AppConstants.LOGIN_AUTH_CODE -> {
AGConnectAuth.getInstance().signOut()
val authHuaweiIdTask: Task<AuthHuaweiId> =
HuaweiIdAuthManager.parseAuthResultFromIntent(data)
if (authHuaweiIdTask.isSuccessful) {
huaweiAccount = authHuaweiIdTask.result
Log.d(
TAG,
AppConstants.LOGIN_GET_ACCESS_TOKEN
)
val credential = HwIdAuthProvider.credentialWithToken(huaweiAccount?.accessToken)
agConnectAuth.signIn(credential)
?.addOnSuccessListener {
it.user.displayName
it.user.email
it.user.uid
it.user.providerInfo
mCloudDBZoneWrapper
.setmUiCallBack(this)
mCloudDBZoneWrapper
.openCloudDBZoneV2()
}
?.addOnFailureListener {
Log.e(TAG, AppConstants.LOGIN_FAILED)
}
} else {
Log.e(
TAG,
AppConstants.LOGIN_FAILED
)
}
}
接入地图服务
地图服务给您提供一套地图开发调用的SDK,地图数据覆盖超过200个国家和地区,支持70多种地图展示与搜索语言,方便您轻松地在应用中集成地图相关的功能,全方位提升用户体验。
在本项目中,该服务用于在地图上展示用户当前位置和修理店位置并为用户规划路线。
接入地图服务具体如下:
1.添加下述依赖集成地图服务。
implementation 'com.huawei.hms:maps:5.0.5.301'
2.初始化Map View。
MapsInitializer.setApiKey(AppConstants.API_KEY)
mMapView.onCreate(mapViewBundle)
mMapView.getMapAsync(this)
3.加载Map View。
/**
*To load Map View
*/
Override fun onMapReady(huaweiMap: HuaweiMap) {
latLng1 = LatLng(Utils.curentLatitude, Utils.currentLongitude)
latLng2 = lat?.let { lng?.let { it1 -> LatLng(it, it1) } }
hMap = huaweiMap
hMap?.isMyLocationEnabled = true
val build = CameraPosition.Builder().target(latLng1).zoom(3f).tilt(45f).build()
val cameraUpdate = CameraUpdateFactory.newCameraPosition(build)
hMap?.apply {
animateCamera(cameraUpdate)
moveCamera(cameraUpdate)
}
addOriginMarker(latLng1!!)
latLng2?.let { addDestinationMarker(it) }
removePolylines()
hMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng1, 10f))
mMarkerOrigin?.showInfoWindow()
hMap?.apply {
moveCamera(CameraUpdateFactory.newLatLngZoom(latLng2, 10f))
resetMinMaxZoomPreference()
}
mMarkerDestination?.showInfoWindow()
}
4.在地图上展示用户/修理者位置。
说明:更多详细信息请参考地图服务接入流程。
/**
* This method shows a marker for Consumer location on Map.
*/
private fun addOriginMarker(latLng: LatLng) {
if (null != mMarkerOrigin) {
mMarkerOrigin?.remove()
}
val address = getCompleteAddressString(Utils.curentLatitude, Utils.currentLongitude)
mMarkerOrigin = hMap?.addMarker(
MarkerOptions().position(latLng)
.anchorMarker(0.5f, 0.9f)
.title("Current Location")
.snippet(address)
)
}
集成定位服务
Android定位SDK采用全球卫星导航系统(Global Navigation Satellite System,简称GNSS)、Wi-Fi、基站等多途径的混合定位模式进行定位,赋予您的应用灵活的全球定位能力。目前,该服务提供融合定位、活动识别、地理围栏等主要能力。
1.添加下述依赖集成定位服务。
implementation 'com.huawei.hms:location:5.0.4.300'
2.获取用户当前位置坐标(经度和纬度)。
/**
*This method shows a marker for Service Provider location on HMS Map
*/
private fun addDestinationMarker(latLng: LatLng) {
if (null != mMarkerDestination) {
mMarkerDestination?.remove()
}
mMarkerDestination = hMap?.addMarker(
MarkerOptions().position(latLng).anchorMarker(0.5f, 0.9f).title(storeName)
.snippet(storeAddress)
)
}
3.在Android manifest文件中添加位置权限。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
4.获取用户当前更新位置坐标(经度和纬度)。
/**
*This method fetches location updates
*/
private fun startLocationUpdates() {
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
}
private val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult ?: return
for (location in locationResult.locations) {
setLocationData(location)
}
}
}
/**
* To set location data.
*/
private fun setLocationData(location: Location) {
value = LocationModel(longitude = location.longitude, latitude = location.latitude)
}
5.获取最新位置信息。
说明:更多详细信息请参考定位服务接入流程。
/**
* To fetch last location information
*/
override fun onActive() {
super.onActive()
fusedLocationClient.lastLocation
.addOnSuccessListener { location: Location? ->
location?.also {
setLocationData(it)
}
}
startLocationUpdates()
}
集成用户身份服务
用户身份服务为用户提供统一的地址管理服务,包括地址录入、编辑、删除和查询,支持用户一键授权应用使用地址信息,高效便利。
1.添加下述依赖集成用户身份服务。
implementation 'com.huawei.hms:identity:5.1.0.300'
2.通过用户身份服务获取用户地址信息。
/**
* To fetch user address from Identity kit
*/
private fun getUserAddress() {
val task = Address.getAddressClient(this@MainActivity).getUserAddress(UserAddressRequest())
task.addOnSuccessListener {
Log.i(TAG, AppConstants.LOGIN_USER_DATA_SUCCESS)
try {
startActivityForResult(it)
} catch (ex: IntentSender.SendIntentException) {
Log.d(TAG, "SendIntentException")
}
}.addOnFailureListener {
Log.i(TAG, AppConstants.LOGIN_USER_DATA_FAILED)
}
}
3.在用户首次登录时调用下述回调从用户身份服务提供的地址列表中选择地址。
/**
* To fetch user address result.
*/
private fun startActivityForResult(result: GetUserAddressResult) {
val status = result.status
if (result.returnCode == 0 && status.hasResolution()) {
Log.i(TAG, AppConstants.LOGIN_RESULT_RES)
status.startResolutionForResult(
this@MainActivity, AppConstants.LOGIN_GET_ADDRESS_REQUESTCODE
)
} else {
Log.i(TAG, AppConstants.LOGIN_RESULT_RES_FAILED)
Utils.showToast(this@MainActivity, getString(R.string.msg_failed_user_resolution))
}
}
4.读取用户地址。
说明:更新详细信息,请参考用户身份服务接入流程。
/**
* To read user address result.
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when(requestCode) {
AppConstants.LOGIN_GET_ADDRESS_REQUESTCODE -> {
onGetAddressResult(resultCode, data)
fragmentCommunicator?.passDataToFragment(data)
}
}
}
集成位置服务
位置服务提供位置查询服务,帮助您的用户更加方便地使用位置相关服务,包括关键字搜索、周边搜索、地点详情、及地点搜索建议等,有助于您的App吸引更多用户,提升用户粘性。
1.添加下述依赖集成位置服务。
implementation 'com.huawei.hms:site:5.0.2.300'
2.初始化位置服务。
searchService = SearchServiceFactory.create(this, Utils.getApiKey())
3.通过用户身份服务获取用户地址信息。
说明:更多详细信息,请参考位置服务接入流程。
/**
*To fetch nearby stores based on user's current location
*/
intent.let {
val request = NearbySearchRequest().apply {
queryString=it.getStringExtra(AppConstants.REQUEST_QUERY).toString()
setQuery(queryString)
setLocation(
Coordinate(
it.getDoubleExtra(AppConstants.SERVICE_LAT_KEY, 0.0),
it.getDoubleExtra(AppConstants.SERVICE_LNG_KEY, 0.0)
)
)
}
imageString = it.getStringExtra(AppConstants.PROVIDER_IMAGE_KEY).toString()
searchService?.nearbySearch(request, searchResultListener)
}
集成云数据库
在这个步骤中,您可以学到:
- 如何使用云数据库开发应用
- 如何向云数据库中写入应用数据
- 如何查询数据
- 如何实时监听数据变化
- 端侧和云侧的数据同步
- 华为云数据库是一款端云协同的数据库产品,提供端云数据的协同管理、统一的数据模型和丰富的数据管理API接口等能力。
该云数据库十分契合本工程项目,有利于我们进行数据的增、删、查、改操作。
开发准备
使用云数据库构建应用服务需完成下述准备工作:
- 在AppGallery Connect注册账号并通过实名认证。
- 登录AppGallery Connect创建项目及应用。
- 开通AppGallery Connect匿名帐号认证服务,使应用有认证用户的相关权限。
- 本地上安装Android Studio。
开通服务
使用云数据库前,您需要先开通服务。
1.登录AppGallery Connect,点击“我的项目”。
2.在项目列表中选择项目和需要开通云数据库的应用。
3.在导航树上选择“构建”,点击“云数据库”。
4.点击“立即开通”。
5.如果您之前没有选择数据处理位置,开通云数据库后首先将会设置数据处理位置。
6.云数据库初始化完成后,该服务成功开通。
新增和导出对象类型
下述示例将展示如果在AppGallery Connect上新增和导出用于Android应用开发的java格式对象类型文件。
1.登录AppGallery Connect,选择“我的项目”。
2.在项目列表页面中选择项目,单击项目下需要创建对象类型的应用。
3.在导航树上选择“构建”,点击“云数据库”。
4.点击“新增”,进入创建对象类型页面。
5.输入对象类型名为LoginInfo后,点击“下一步”。
6.点击“+新增字段”,新增如下字段后,单击“下一步”。
字段名称 |
类型 |
主键 |
非空 |
加密 |
默认值 |
user_id |
Integer |
√ |
√ |
– |
– |
user_email |
String |
– |
– |
– |
– |
user_name |
String |
– |
– |
– |
– |
user_phone |
Double |
– |
– |
– |
– |
photo_uri |
String |
– |
– |
– |
– |
device_token |
Date |
– |
– |
– |
– |
shadowFlag |
Boolean |
– |
– |
– |
true |
7.(可选)点击“新增索引”。
8.按照如下要求设置各角色权限后,点击“下一步”。
角色 |
query |
upsert |
delete |
所有人 |
√ |
– |
– |
认证用户 |
√ |
√ |
√ |
数据创建者 |
√ |
√ |
√ |
管理员 |
√ |
√ |
√ |
9.点击“确定”。
在对象类型列表中可以看到已创建的对象类型。
重复上述步骤,完成Service type、Service Category对象类型的创建。
10.点击“导出”。
11.设置导出文件格式为java格式。
12.设置java文件类型为“android”。
13.输入java文件中的包名。
包名只能包含以下3种字符:
字母(A-Z或a-z)
数字(0-9)
特殊字符:_和.
14. 点击“导出”。
文件将会导出至本地,其内包含该版本中所有的对象类型。导出的java格式文件在后续步骤用于添加至本地开发环境。
新增存储区
您可基于AppGallery Connect在云侧创建数据存储区,请您遵循操作步骤创建一个存储区名称为“UrbanHomeServices”的存储区。
1.登录AppGallery Connect,点击“我的项目”。
2.在项目列表页面中选择项目,单击项目下需要创建存储区的应用。
3.在导航树上选择“构建 > 云数据库”。
4.选择“存储区”页签。
5.点击“新增”,进入创建存储区页面。
6.输入存储区名称为“UrbanHomeSevices”。
7.点击“确定”。
8.创建完成后返回存储区列表中,可以查看已创建的存储区。
配置开发环境
1.在项目级的/app/build.gradle文件中dependencies节点添加Cloud DB SDK。
implementation 'com.huawei.agconnect:agconnect=database:1.2.3.301'
2.在build.gradle文件中设置Java源码兼容模式为JDK1.8版本。
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
添加对象类型文件
本地应用开发无需再次创建对象类型。
1.将已在AppGallery Connect上导出的全部java格式文件添加至本地开发环境。
2.Initialize Cloud DB. 通过AGConnectCloudDB类中的createObjectType()方法实现对象类型的定义和创建。
初始化
在添加对象类型文件后,您就可以使用云数据库进行应用开发。开发应用时,需要先初始化AGConnectCloudDB,然后创建Cloud DB zone和对象类型。
1.在应用的CloudDBZoneWrapper类中初始化AGConnectCloudDB。
/**
* To initialize AGConnectCloudDB
*/
public static void initAGConnectCloudDB(Context context) {
AGConnectCloudDB.initialize(context);
}
2.获取AGConnectCloudDB实例和创建对象类型。
mCloudDB = AGConnectCloudDB.getInstance();
mCloudDB.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo());
3.创建Cloud DB zone配置对象,并打开该Cloud DB zone。
/**
* This method is used to open Cloud DB zone.
*/
public void openCloudDBZoneV2() {
mConfig = new CloudDBZoneConfig(AppConstants.URBAN_HOME_SERVICES,
CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE, CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC);
mConfig.setPersistenceEnabled(true);
Task<CloudDBZone> openDBZoneTask = mCloudDB.openCloudDBZone2(mConfig, true);
openDBZoneTask.addOnSuccessListener(cloudDBZone -> {
Log.w(TAG, "open clouddbzone success");
mCloudDBZone = cloudDBZone;
// Add subscription after opening cloudDBZone success
mUiCallBack.onInitCloud();
addSubscription();
}).addOnFailureListener(e ->
Log.w(TAG, "open clouddbzone failed for"));
}
写入数据
您可以使用executeUpsert()接口向当前Cloud DB zone中写入一个或一组对象。
/**
* This method is used to insert data into Cloud DB.
*/
public void insertDbZoneInfo(T objectInfo) {
if (mCloudDBZone == null) {
Log.w(TAG, "CloudDBZone is null, try re-open it");
return;
}
Task<Integer> upsertTask = mCloudDBZone.executeUpsert(objectInfo);
upsertTask.addOnSuccessListener(cloudDBZoneResult -> {
mUiCallBack.onInsertSuccess(cloudDBZoneResult);
}).addOnFailureListener(e -> {
mUiCallBack.updateUiOnError("Insert table info failed");
});
}
查看数据
用户在应用界面中新增的数据,将会被存储在云侧。在端侧注册数据变化监听器,当云侧数据发生变化时,端侧能够感知数据变化,及时刷新本地应用数据。
调用subscribeSnapshot()方法并设置查询条件可以指定监听对象。当监听对象的数据发生变化时,端侧会收到通知,根据快照获取数据变化信息,从云侧同步数据至端侧应用。
/**
* This listener is used to get snapshot
*/
private OnSnapshotListener<T> mSnapshotListener = (cloudDBZoneSnapshot, e) -> {
if (e != null) {
Log.w(TAG, "onSnapshot" );
return;
}
CloudDBZoneObjectList<T> snapshotObjects = cloudDBZoneSnapshot.getSnapshotObjects();
List<T> dbZoneList = new ArrayList<>();
try {
if (snapshotObjects != null) {
while (snapshotObjects.hasNext()) {
T objectInfo = snapshotObjects.next();
dbZoneList.add(objectInfo);
}
}
mUiCallBack.onSubscribe(dbZoneList);
} catch (AGConnectCloudDBException snapshotException) {
Log.w(TAG, "onSnapshot:(getObject)");
} finally {
cloudDBZoneSnapshot.release();
}
};
查询数据
您可以通过executeQuery()、addOnSuccessListener()和addOnFailureListener()方法组合,实现异步方式查询数据。
/**
* This method is used to query all data from Cloud DB.
*/
public void queryAllData(CloudDBZoneQuery<T> query) {
if (mCloudDBZone == null) {
Log.w(TAG, "CloudDBZone is null, try re-open it");
return;
}
Task<CloudDBZoneSnapshot<T>> queryTask = mCloudDBZone.executeQuery(query,
CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY);
queryTask.addOnSuccessListener(new OnSuccessListener<CloudDBZoneSnapshot<T>>() {
@Override
public void onSuccess(CloudDBZoneSnapshot<T> snapshot) {
processQueryResult(snapshot);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
mUiCallBack.updateUiOnError("Query failed");
}
});
}
删除数据
您可以使用executeDelete()方法删除一个或一组对象。删除数据时,Cloud DB会根据传入对象主键删除相应的数据,不会比对该对象其它属性与存储的数据是否一致。删除一组对象时,删除操作是原子的,即对象列表中的对象要么全部删除成功,要么全部删除失败。
/**
* This method is used delete table data on Cloud DB.
*/
public void deleteTableData(List<T> tableObject) {
if (mCloudDBZone == null) {
Log.w(TAG, "CloudDBZone is null, try re-open it");
return;
}
Task<Integer> deleteTask = mCloudDBZone.executeDelete(tableObject);
if (deleteTask.getException() != null) {
mUiCallBack.updateUiOnError("Delete service type table failed");
return;
}
mUiCallBack.onDelete(tableObject);
}
}
编辑数据
您可以使用editService()方法编辑修理工的信息。
/**
* This method is used to edit Service details.
*/
override fun editService(listObject: ServiceType) {
val intent = Intent(this, AddServiceActivity::class.java)
intent.apply {
putExtra(AppConstants.CATEGORY_NAME, listObject.cat_name)
putExtra(AppConstants.PROVIDER_PH_NUM, listObject.phone_number.toString())
putExtra(AppConstants.PROVIDER_MAIL_ID, listObject.email_id)
putExtra(AppConstants.PROVIDER_COUNTRY, listObject.country)
putExtra(AppConstants.PROVIDER_ID, listObject.id)
putExtra(AppConstants.PROVIDER_NAME, listObject.service_provider_name)
putExtra(AppConstants.PROVIDER_CITY, listObject.city)
putExtra(AppConstants.PROVIDER_STATE, listObject.state)
}
startActivity(intent)
}
提示:
- 请务必使用最新版本的依赖。
- 请务必在对象类型中为用户分配合理的角色。
说明:更多详细信息,请参考云数据库接入文档。
恭喜您
祝贺您,您已成功构建UrbanHome。
参考
有关更多信息,请参阅以下官方文档。
本Codelab中的示例代码下载地址如下:源码下载
欲了解更多更全技术文章,欢迎访问https://developer.huawei.com/consumer/cn/forum/?ha_source=zzh
【多服务场景化解决方案】智能家居(UrbanHome)的更多相关文章
- 【多服务场景化解决方案】AR虚拟技术助力智能家装
1 .介绍 总览 本应用采用了华为图形引擎服务的AR虚拟技术,您可以在手机相机里摆放想要购置的家具家电,交互式体验让您可以轻松操控它们的3D图例,以此来确定这些家具家电是否适合摆放在您的家里. 特 ...
- 智能家居巨头 Aqara 基于 KubeSphere 打造物联网微服务平台
背景 从传统运维到容器化的 Docker Swarm 编排,从 Docker Swarm 转向 Kubernetes,然后在 Kubernetes 运行 SpringCloud 微服务全家桶,到最终拥 ...
- 金融即服务(FaaS),将开启场景化金融新格局
转自: https://www.iyiou.com/p/28494/fs/1 [ 亿欧导读 ] 金融即服务揭示了场景金融的实现路径,通过双向连接做一个开放的系统,按需给客户提供金融服务. 本文系作者在 ...
- SAP Leonardo图片处理相关的机器学习服务在SAP智能服务场景中的应用
本文作为Jerry最近正在做的一个项目的工作思路的梳理. 我们假设这样一个服务场景,技师上门维修某设备,发现设备上某零件损坏了,假设这位技师由于种种原因,没能根据自己的经验识别出这个零件的型号.此时技 ...
- 基于能量收集的智能家居-2013国家级大学生创业实践项目申报_商业计划书_V0.2
SmartHome项目商业计划 基于能量收集的 免电池无线智能家居系统 IA-SmartHome团队 2012.12 l 基于无线的智能家居解决方案,节省施工成本: l 基于能 ...
- 一百元的智能家居——Asp.Net Mvc Api+讯飞语音+Android+Arduino
大半夜的,先说些废话提提神 如今智能家居已经不再停留在概念阶段,高大上的科技公司都已经推出了自己的部分或全套的智能家居解决方案,不过就目前的现状而言,大多还停留在展厅阶段,还没有广泛的推广起来,有人说 ...
- 阿里云场景化阿里云企业数字化转型售前方法PSA
阿里云场景化阿里云企业数字化转型售前方法PSA 目录 01 课程收获 理解企业数字化转型的概念.内涵.本质 了解企业数字化转型的要点.目标和切入点 掌握数字化转型项目售前阶段实践方法 场景化方案 阿里 ...
- zigbee智能家居基础扫盲
zigbee Zigbee是基于IEEE802.15.4标准的低功耗个域网协议.根据这个协议规定的技术是一种短距离.低功耗的无线通信技术.这一名称来源于蜜蜂的八字舞,由于蜜蜂(bee)是靠飞翔和&qu ...
- 一款新型的智能家居WiFi选择方案——SimpleWiFi在无线智能家居中的应用
一款新型的智能家居WiFi选择方案——SimpleWiFi在无线智能家居中的应用 先上图: 随着科学技术的不断发展,局域网也正逐渐向无线化,多网合一的方向发展,在这个多网合一快速发展过程中,带 ...
随机推荐
- robotframework之环境安装
一.安装python2.7环境,python --version查询python安装的版本 二.setuptools安装
- vscode常用插件快捷键
俗话说,工欲善其事必先利其器,我们码农的器是什么尼?没错,就是我们亲爱的IDE,前端开发者最爱的编辑器应该是vscode了吧.但是我们要怎么去锋利它尼?不外乎就是熟悉它的使用方法.快捷键以及第三方的插 ...
- WPF开发随笔收录-自定义图标控件
一.前言 1.在以前自学的过程中,软件需要使用到图标的时候,总是第一个想法是下载一个图片来充当图标使用,但实际得出来的效果会出现模糊的现象.后来网上学习了字体图标库的用法,可以在阿里云矢量图网站那里将 ...
- 从位图到布隆过滤器,C#实现
前言 本文将以 C# 语言来实现一个简单的布隆过滤器,为简化说明,设计得很简单,仅供学习使用. 感谢@时总百忙之中的指导. 布隆过滤器简介 布隆过滤器(Bloom filter)是一种特殊的 Hash ...
- Tapdata Cloud 2.1.2 来啦:大波细节已就绪!字段类型可批量修改、支持微信扫码登录、新增支持 Vika 为目标
Tapdata Cloud cloud.tapdata.net 让数据实时可用 Tapdata Cloud 是国内首家异构数据库实时同步云平台,目前支持 Oracle.MySQL.PG.SQL Ser ...
- CSS进阶内容——布局技巧和细节修饰
CSS进阶内容--布局技巧和细节修饰 我们在之前的文章中已经掌握了CSS的大部分内容,但仍有一些内容我们没有涉略,这篇文章就是为了补充前面没有涉及的内容,为我们的知识做出补充并且介绍一些布局技巧 当然 ...
- 螣龙安科反入侵:EDR的缺点
EDR解决方案提供了比传统终结点安全解决方案更高的功能,并且可以增加人员数量,但是这些功能都有不少的缺点. EDR功能付出巨大代价 在过去四年中,虽然产品成本平均每年下降约35%,但即使到今天,产品的 ...
- warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8): No such file or directory
1)apt-get clean && apt-get update && apt-get install -y locales 2)locale-gen en_US.U ...
- 记一次react-hooks项目获取图表图片集合并生成pdf的需求
需求: 获取子组件中所有图片的dom元素并生成图片,再把生成的图片转化为pdf下载 难点 众所周知,react是单向数据流,倡导f(data)⇒ UI的哲学, 并不建议过多直接操作dom,但是生成图片 ...
- IP核的使用(Vivado中的调用,product guide的查询阅读 ,引脚的设置(位宽,个数,算法等),coe文件的初始化 )
IP核:Intellectual Property core ,即知识产权核.每个IP核可以实现特定功能,我们在设计一个东西时可以直接调用某个IP核来辅助实现功能. 存在形式:HDL语言形式,网表形式 ...