1// Copyright 2023 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15syntax = "proto3"; 16 17package google.maps.solar.v1; 18 19import "google/api/annotations.proto"; 20import "google/api/client.proto"; 21import "google/api/field_behavior.proto"; 22import "google/api/httpbody.proto"; 23import "google/type/date.proto"; 24import "google/type/latlng.proto"; 25import "google/type/money.proto"; 26 27option csharp_namespace = "Google.Maps.Solar.V1"; 28option go_package = "cloud.google.com/go/maps/solar/apiv1/solarpb;solarpb"; 29option java_multiple_files = true; 30option java_outer_classname = "SolarServiceProto"; 31option java_package = "com.google.maps.solar.v1"; 32option objc_class_prefix = "GGMPV1A"; 33option php_namespace = "Google\\Maps\\Solar\\V1"; 34option ruby_package = "Google::Maps::Solar::V1"; 35 36// Service definition for the Solar API. 37service Solar { 38 option (google.api.default_host) = "solar.googleapis.com"; 39 option (google.api.oauth_scopes) = 40 "https://www.googleapis.com/auth/cloud-platform"; 41 42 // Locates the closest building to a query point. Returns an error with 43 // code `NOT_FOUND` if there are no buildings within approximately 50m of the 44 // query point. 45 rpc FindClosestBuildingInsights(FindClosestBuildingInsightsRequest) 46 returns (BuildingInsights) { 47 option (google.api.http) = { 48 get: "/v1/buildingInsights:findClosest" 49 }; 50 } 51 52 // Gets solar information for a region surrounding a location. 53 // Returns an error with code `NOT_FOUND` if the location is outside 54 // the coverage area. 55 rpc GetDataLayers(GetDataLayersRequest) returns (DataLayers) { 56 option (google.api.http) = { 57 get: "/v1/dataLayers:get" 58 }; 59 } 60 61 // Returns an image by its ID. 62 rpc GetGeoTiff(GetGeoTiffRequest) returns (google.api.HttpBody) { 63 option (google.api.http) = { 64 get: "/v1/geoTiff:get" 65 }; 66 } 67} 68 69// Request message for `Solar.FindClosestBuildingInsights`. 70message FindClosestBuildingInsightsRequest { 71 // Required. The longitude and latitude from which the API looks for the 72 // nearest known building. 73 google.type.LatLng location = 1 [(google.api.field_behavior) = REQUIRED]; 74 75 // Optional. The minimum quality level allowed in the results. No result with 76 // lower quality than this will be returned. Not specifying this is 77 // equivalent to restricting to HIGH quality only. 78 ImageryQuality required_quality = 3 [(google.api.field_behavior) = OPTIONAL]; 79 80 // Optional. Whether to require exact quality of the imagery. 81 // If set to false, the `required_quality` field is interpreted as the minimum 82 // required quality, such that HIGH quality imagery may be returned when 83 // `required_quality` is set to MEDIUM. If set to true, `required_quality` 84 // is interpreted as the exact required quality and only `MEDIUM` quality 85 // imagery is returned if `required_quality` is set to `MEDIUM`. 86 bool exact_quality_required = 4 [(google.api.field_behavior) = OPTIONAL]; 87} 88 89// A bounding box in lat/lng coordinates. 90message LatLngBox { 91 // The southwest corner of the box. 92 google.type.LatLng sw = 1; 93 94 // The northeast corner of the box. 95 google.type.LatLng ne = 2; 96} 97 98// Response message for `Solar.FindClosestBuildingInsights`. 99// Information about the location, dimensions, and solar potential of a 100// building. 101message BuildingInsights { 102 // The resource name for the building, of the format `building/<place ID>`. 103 string name = 1; 104 105 // A point near the center of the building. 106 google.type.LatLng center = 2; 107 108 // The bounding box of the building. 109 LatLngBox bounding_box = 9; 110 111 // Date that the underlying imagery was acquired. This is approximate. 112 google.type.Date imagery_date = 3; 113 114 // When processing was completed on this imagery. 115 google.type.Date imagery_processed_date = 11; 116 117 // Postal code (e.g., US zip code) this building is contained by. 118 string postal_code = 4; 119 120 // Administrative area 1 (e.g., in the US, the state) that contains this 121 // building. For example, in the US, the abbreviation might be "MA" or "CA." 122 string administrative_area = 5; 123 124 // Statistical area (e.g., US census tract) this building is in. 125 string statistical_area = 6; 126 127 // Region code for the country (or region) this building is in. 128 string region_code = 7; 129 130 // Solar potential of the building. 131 SolarPotential solar_potential = 8; 132 133 // The quality of the imagery used to compute the data for this building. 134 ImageryQuality imagery_quality = 10; 135} 136 137// Information about the solar potential of a building. A number of 138// fields in this are defined in terms of "panels". The fields 139// [panel_capacity_watts] 140// [google.maps.solar.v1.SolarPotential.panel_capacity_watts], 141// [panel_height_meters] 142// [google.maps.solar.v1.SolarPotential.panel_height_meters], 143// and [panel_width_meters] 144// [google.maps.solar.v1.SolarPotential.panel_width_meters] 145// describe the parameters of the model of panel used in these 146// calculations. 147message SolarPotential { 148 // Size of the maximum array - that is, the maximum number of panels that 149 // can fit on the roof. 150 int32 max_array_panels_count = 1; 151 152 // Capacity, in watts, of the panel used in the calculations. 153 float panel_capacity_watts = 9; 154 155 // Height, in meters in portrait orientation, of the panel used in 156 // the calculations. 157 float panel_height_meters = 10; 158 159 // Width, in meters in portrait orientation, of the panel used in 160 // the calculations. 161 float panel_width_meters = 11; 162 163 // The expected lifetime, in years, of the solar panels. This is 164 // used in the financial calculations. 165 int32 panel_lifetime_years = 12; 166 167 // Size, in square meters, of the maximum array. 168 float max_array_area_meters2 = 2; 169 170 // Maximum number of sunshine hours received per year, by any point 171 // on the roof. Sunshine hours are a measure of the total amount of 172 // insolation (energy) received per year. 1 sunshine hour = 1 kWh per kW 173 // (where kW refers to kW of capacity under Standard Testing Conditions). 174 float max_sunshine_hours_per_year = 3; 175 176 // Equivalent amount of CO2 produced per MWh of grid electricity. This 177 // is a measure of the carbon intensity of grid electricity displaced 178 // by solar electricity. 179 float carbon_offset_factor_kg_per_mwh = 4; 180 181 // Total size and sunlight quantiles for the part of the roof that 182 // was assigned to some roof segment. Despite the name, this may not 183 // include the entire building. See [building_stats] 184 // [google.maps.solar.v1.SolarPotential.building_stats]. 185 SizeAndSunshineStats whole_roof_stats = 5; 186 187 // Size and sunlight quantiles for the entire building, including 188 // parts of the roof that were not assigned to some roof segment. 189 // Because the orientations of these parts are not well 190 // characterised, the roof area estimate is unreliable, but the 191 // ground area estimate is reliable. It may be that a more reliable 192 // whole building roof area can be obtained by scaling the roof area 193 // from [whole_roof_stats] 194 // [google.maps.solar.v1.SolarPotential.whole_roof_stats] by 195 // the ratio of the ground areas of `building_stats` and 196 // `whole_roof_stats`. 197 SizeAndSunshineStats building_stats = 13; 198 199 // Size and sunlight quantiles for each roof segment. 200 repeated RoofSegmentSizeAndSunshineStats roof_segment_stats = 6; 201 202 // Each [SolarPanel] [google.maps.solar.v1.SolarPanel] 203 // describes a single solar panel. They are listed in the order that 204 // the panel layout algorithm placed this. This is usually, though 205 // not always, in decreasing order of annual energy production. 206 repeated SolarPanel solar_panels = 14; 207 208 // Each [SolarPanelConfig] 209 // [google.maps.solar.v1.SolarPanelConfig] describes a 210 // different arrangement of solar panels on the roof. They are in 211 // order of increasing number of panels. The `SolarPanelConfig` with 212 // [panels_count] 213 // [google.maps.solar.v1.SolarPanelConfig.panels_count]=N is 214 // based on the first N panels in the `solar_panels` list. This field is only 215 // populated if at least 4 panels can fit on a roof. 216 repeated SolarPanelConfig solar_panel_configs = 7; 217 218 // A [FinancialAnalysis] 219 // [google.maps.solar.v1.FinancialAnalysis] gives the savings 220 // from going solar assuming a given monthly bill and a given 221 // electricity provider. They are in order of increasing order of 222 // monthly bill amount. This field will be empty for buildings in 223 // areas for which the Solar API does not have enough information to 224 // perform financial computations. 225 repeated FinancialAnalysis financial_analyses = 8; 226} 227 228// Information about the size and sunniness quantiles of a roof segment. 229message RoofSegmentSizeAndSunshineStats { 230 // Angle of the roof segment relative to the theoretical ground plane. 231 // 0 = parallel to the ground, 90 = perpendicular to the ground. 232 optional float pitch_degrees = 1; 233 234 // Compass direction the roof segment is pointing in. 0 = North, 90 = 235 // East, 180 = South. For a "flat" roof segment (`pitch_degrees` very 236 // near 0), azimuth is not well defined, so for consistency, we define it 237 // arbitrarily to be 0 (North). 238 optional float azimuth_degrees = 2; 239 240 // Total size and sunlight quantiles for the roof segment. 241 SizeAndSunshineStats stats = 3; 242 243 // A point near the center of the roof segment. 244 google.type.LatLng center = 4; 245 246 // The bounding box of the roof segment. 247 LatLngBox bounding_box = 5; 248 249 // The height of the roof segment plane, in meters above sea level, 250 // at the point designated by `center`. Together with the pitch, 251 // azimuth, and center location, this fully defines the roof segment 252 // plane. 253 optional float plane_height_at_center_meters = 6; 254} 255 256// Size and sunniness quantiles of a roof, or part of a roof. 257message SizeAndSunshineStats { 258 // The area of the roof or roof segment, in m^2. This is the roof area 259 // (accounting for tilt), not the ground footprint area. 260 float area_meters2 = 1; 261 262 // Quantiles of the pointwise sunniness across the area. If there 263 // are N values here, this represents the (N-1)-iles. For example, 264 // if there are 5 values, then they would be the quartiles (min, 265 // 25%, 50%, 75%, max). Values are in annual kWh/kW like 266 // [max_sunshine_hours_per_year] 267 // [google.maps.solar.v1.SolarPotential.max_sunshine_hours_per_year]. 268 repeated float sunshine_quantiles = 2; 269 270 // The ground footprint area covered by the roof or roof segment, in m^2. 271 float ground_area_meters2 = 3; 272} 273 274// SolarPanel describes the position, orientation, and production of a 275// single solar panel. See the [panel_height_meters] 276// [google.maps.solar.v1.SolarPotential.panel_height_meters], 277// [panel_width_meters] 278// [google.maps.solar.v1.SolarPotential.panel_width_meters], 279// and [panel_capacity_watts] 280// [google.maps.solar.v1.SolarPotential.panel_capacity_watts] 281// fields in [SolarPotential] 282// [google.maps.solar.v1.SolarPotential] for information on the 283// parameters of the panel. 284message SolarPanel { 285 // The centre of the panel. 286 google.type.LatLng center = 1; 287 288 // The orientation of the panel. 289 SolarPanelOrientation orientation = 2; 290 291 // How much sunlight energy this layout captures over the course of a 292 // year, in DC kWh. 293 float yearly_energy_dc_kwh = 3; 294 295 // Index in [roof_segment_stats] 296 // [google.maps.solar.v1.SolarPotential.roof_segment_stats] 297 // of the `RoofSegmentSizeAndSunshineStats` which corresponds to the 298 // roof segment that this panel is placed on. 299 optional int32 segment_index = 4; 300} 301 302// SolarPanelConfig describes a particular placement of solar panels 303// on the roof. 304message SolarPanelConfig { 305 // Total number of panels. Note that this is redundant to (the sum 306 // of) the corresponding fields in [roof_segment_summaries] 307 // [google.maps.solar.v1.SolarPanelConfig.roof_segment_summaries]. 308 int32 panels_count = 1; 309 310 // How much sunlight energy this layout captures over the course of a 311 // year, in DC kWh, assuming the panels described above. 312 float yearly_energy_dc_kwh = 2; 313 314 // Information about the production of each roof segment that is carrying 315 // at least one panel in this layout. `roof_segment_summaries[i]` describes 316 // the i-th roof segment, including its size, expected production and 317 // orientation. 318 repeated RoofSegmentSummary roof_segment_summaries = 4; 319} 320 321// Information about a roof segment on the building, with some number of 322// panels placed on it. 323message RoofSegmentSummary { 324 // Angle of the roof segment relative to the theoretical ground plane. 325 // 0 = parallel to the ground, 90 = perpendicular to the ground. 326 optional float pitch_degrees = 2; 327 328 // Compass direction the roof segment is pointing in. 0 = North, 90 = 329 // East, 180 = South. For a "flat" roof segment (`pitch_degrees` very 330 // near 0), azimuth is not well defined, so for consistency, we define it 331 // arbitrarily to be 0 (North). 332 optional float azimuth_degrees = 3; 333 334 // The total number of panels on this segment. 335 int32 panels_count = 7; 336 337 // How much sunlight energy this part of the layout captures over the 338 // course of a year, in DC kWh, assuming the panels described above. 339 float yearly_energy_dc_kwh = 8; 340 341 // Index in [roof_segment_stats] 342 // [google.maps.solar.v1.SolarPotential.roof_segment_stats] 343 // of the corresponding `RoofSegmentSizeAndSunshineStats`. 344 optional int32 segment_index = 9; 345} 346 347// Analysis of the cost and benefits of the optimum solar layout for a 348// particular electric bill size. 349message FinancialAnalysis { 350 // The monthly electric bill this analysis assumes. 351 google.type.Money monthly_bill = 3; 352 353 // Whether this is the bill size selected to be the default bill for the 354 // area this building is in. Exactly one `FinancialAnalysis` in 355 // `BuildingSolarPotential` should have `default_bill` set. 356 bool default_bill = 4; 357 358 // How much electricity the house uses in an average month, based on the 359 // bill size and the local electricity rates. 360 float average_kwh_per_month = 5; 361 362 // Index in [solar_panel_configs] 363 // [google.maps.solar.v1.SolarPotential.solar_panel_configs] 364 // of the optimum solar layout for this bill size. This can be -1 365 // indicating that there is no layout. In this case, the remaining 366 // submessages will be omitted. 367 optional int32 panel_config_index = 6; 368 369 // Financial information that applies regardless of the financing method 370 // used. 371 FinancialDetails financial_details = 7; 372 373 // Cost and benefit of leasing the solar panels. 374 LeasingSavings leasing_savings = 8; 375 376 // Cost and benefit of buying the solar panels with cash. 377 CashPurchaseSavings cash_purchase_savings = 9; 378 379 // Cost and benefit of buying the solar panels by financing the purchase. 380 FinancedPurchaseSavings financed_purchase_savings = 10; 381} 382 383// Details of a financial analysis. Some of these details are already 384// stored at higher levels (e.g., out of pocket cost). Total money 385// amounts are over a lifetime period defined by the 386// [panel_lifetime_years] 387// [google.maps.solar.v1.SolarPotential.panel_lifetime_years] 388// field in [SolarPotential] 389// [google.maps.solar.v1.SolarPotential]. Note: The out of 390// pocket cost of purchasing the panels is given in the 391// [out_of_pocket_cost] 392// [google.maps.solar.v1.CashPurchaseSavings.out_of_pocket_cost] 393// field in [CashPurchaseSavings] 394// [google.maps.solar.v1.CashPurchaseSavings]. 395message FinancialDetails { 396 // How many AC kWh we think the solar panels will generate in their first 397 // year. 398 float initial_ac_kwh_per_year = 1; 399 400 // Utility bill for electricity not produced by solar, for the 401 // lifetime of the panels. 402 google.type.Money remaining_lifetime_utility_bill = 2; 403 404 // Amount of money available from federal incentives; this applies if the 405 // user buys (with or without a loan) the panels. 406 google.type.Money federal_incentive = 3; 407 408 // Amount of money available from state incentives; this applies if the 409 // user buys (with or without a loan) the panels. 410 google.type.Money state_incentive = 4; 411 412 // Amount of money available from utility incentives; this applies if the 413 // user buys (with or without a loan) the panels. 414 google.type.Money utility_incentive = 5; 415 416 // Amount of money the user will receive from Solar Renewable Energy 417 // Credits over the panel lifetime; this applies if the user buys 418 // (with or without a loan) the panels. 419 google.type.Money lifetime_srec_total = 6; 420 421 // Total cost of electricity the user would have paid over the 422 // lifetime period if they didn't install solar. 423 google.type.Money cost_of_electricity_without_solar = 7; 424 425 // Whether net metering is allowed. 426 bool net_metering_allowed = 8; 427 428 // Percentage (0-100) of the user's power supplied by solar. 429 // Valid for the first year but approximately correct for future years. 430 optional float solar_percentage = 9; 431 432 // The percentage (0-100) of solar electricity production we assumed was 433 // exported to the grid, based on the first quarter of production. This 434 // affects the calculations if net metering is not allowed. 435 optional float percentage_exported_to_grid = 10; 436} 437 438// Financial information that's shared between different financing methods. 439message SavingsOverTime { 440 // Savings in the first year after panel installation. 441 google.type.Money savings_year1 = 1; 442 443 // Savings in the first twenty years after panel installation. 444 google.type.Money savings_year20 = 2; 445 446 // Using the assumed discount rate, what is the present value of the 447 // cumulative 20-year savings? 448 google.type.Money present_value_of_savings_year20 = 3; 449 450 // Savings in the entire panel lifetime. 451 google.type.Money savings_lifetime = 5; 452 453 // Using the assumed discount rate, what is the present value of the 454 // cumulative lifetime savings? 455 google.type.Money present_value_of_savings_lifetime = 6; 456 457 // Indicates whether this scenario is financially viable. Will be false for 458 // scenarios with poor financial viability (e.g., money-losing). 459 bool financially_viable = 4; 460} 461 462// Cost and benefit of leasing a particular configuration of solar panels 463// with a particular electricity usage. 464message LeasingSavings { 465 // Whether leases are allowed in this juristiction (leases are not 466 // allowed in some states). If this field is false, then the values in 467 // this message should probably be ignored. 468 bool leases_allowed = 1; 469 470 // Whether leases are supported in this juristiction by the financial 471 // calculation engine. If this field is false, then the values in this 472 // message should probably be ignored. This is independent of 473 // `leases_allowed`: in some areas leases are allowed, but under conditions 474 // that aren't handled by the financial models. 475 bool leases_supported = 2; 476 477 // Estimated annual leasing cost. 478 google.type.Money annual_leasing_cost = 3; 479 480 // How much is saved (or not) over the lifetime period. 481 SavingsOverTime savings = 4; 482} 483 484// Cost and benefit of an outright purchase of a particular configuration 485// of solar panels with a particular electricity usage. 486message CashPurchaseSavings { 487 // Initial cost before tax incentives: the amount that must be paid 488 // out-of-pocket. Contrast with `upfront_cost`, which is after tax incentives. 489 google.type.Money out_of_pocket_cost = 1; 490 491 // Initial cost after tax incentives: it's the amount that must be paid 492 // during first year. Contrast with `out_of_pocket_cost`, which is before tax 493 // incentives. 494 google.type.Money upfront_cost = 2; 495 496 // The value of all tax rebates. 497 google.type.Money rebate_value = 3; 498 499 // Number of years until payback occurs. A negative value means payback 500 // never occurs within the lifetime period. 501 optional float payback_years = 4; 502 503 // How much is saved (or not) over the lifetime period. 504 SavingsOverTime savings = 5; 505} 506 507// Cost and benefit of using a loan to buy a particular configuration 508// of solar panels with a particular electricity usage. 509message FinancedPurchaseSavings { 510 // Annual loan payments. 511 google.type.Money annual_loan_payment = 1; 512 513 // The value of all tax rebates (including Federal Investment Tax Credit 514 // (ITC)). 515 google.type.Money rebate_value = 2; 516 517 // The interest rate on loans assumed in this set of calculations. 518 float loan_interest_rate = 3; 519 520 // How much is saved (or not) over the lifetime period. 521 SavingsOverTime savings = 4; 522} 523 524// Request message for `Solar.GetDataLayers`. 525message GetDataLayersRequest { 526 // Required. The longitude and latitude for the center of the region to get 527 // data for. 528 google.type.LatLng location = 1 [(google.api.field_behavior) = REQUIRED]; 529 530 // Required. The radius, in meters, defining the region surrounding that 531 // centre point for which data should be returned. The limitations 532 // on this value are: 533 // 534 // * Any value up to 100m can always be specified. 535 // * Values over 100m can be specified, as long as 536 // `radius_meters` <= `pixel_size_meters * 1000`. 537 // * However, for values over 175m, the `DataLayerView` in the 538 // request must not include monthly flux or hourly shade. 539 float radius_meters = 2 [(google.api.field_behavior) = REQUIRED]; 540 541 // Optional. The desired subset of the data to return. 542 DataLayerView view = 3 [(google.api.field_behavior) = OPTIONAL]; 543 544 // Optional. The minimum quality level allowed in the results. No result with 545 // lower quality than this will be returned. Not specifying this is 546 // equivalent to restricting to HIGH quality only. 547 ImageryQuality required_quality = 5 [(google.api.field_behavior) = OPTIONAL]; 548 549 // Optional. The minimum scale, in meters per pixel, of the data to return. 550 // Values of 0.1 (the default, if this field is not set explicitly), 551 // 0.25, 0.5, and 1.0 are supported. Imagery components whose normal 552 // resolution is less than `pixel_size_meters` will be returned at 553 // the resolution specified by `pixel_size_meters`; imagery 554 // components whose normal resolution is equal to or greater than 555 // `pixel_size_meters` will be returned at that normal resolution. 556 float pixel_size_meters = 6 [(google.api.field_behavior) = OPTIONAL]; 557 558 // Optional. Whether to require exact quality of the imagery. 559 // If set to false, the `required_quality` field is interpreted as the minimum 560 // required quality, such that HIGH quality imagery may be returned when 561 // `required_quality` is set to MEDIUM. If set to true, `required_quality` 562 // is interpreted as the exact required quality and only `MEDIUM` quality 563 // imagery is returned if `required_quality` is set to `MEDIUM`. 564 bool exact_quality_required = 7 [(google.api.field_behavior) = OPTIONAL]; 565} 566 567// Information about the solar potential of a region. The actual data 568// are contained in a number of GeoTIFF files covering the requested 569// region, for which this message contains URLs: Each string in the 570// `DataLayers` message contains a URL from which the 571// corresponding GeoTIFF can be fetched. These URLs are valid for a 572// few hours after they've been generated. Most of the GeoTIFF files 573// are at a resolution of 0.1m/pixel, but the monthly flux file is at 574// 0.5m/pixel, and the hourly shade files are at 1m/pixel. If a 575// `pixel_size_meters` value was specified in the 576// `GetDataLayersRequest`, then the minimum resolution in the GeoTIFF 577// files will be that value. 578message DataLayers { 579 // When the source imagery (from which all the other data are derived) in this 580 // region was taken. It is necessarily somewhat approximate, as the images may 581 // have been taken over more than one day. 582 google.type.Date imagery_date = 1; 583 584 // When processing was completed on this imagery. 585 google.type.Date imagery_processed_date = 2; 586 587 // The URL for an image of the DSM (Digital Surface Model) of the region. 588 // Values are in meters above EGM96 geoid (i.e., sea level). Invalid locations 589 // (where we don't have data) are stored as -9999. 590 string dsm_url = 3; 591 592 // The URL for an image of RGB data (aerial photo) of the region. 593 string rgb_url = 4; 594 595 // The URL for the building mask image: one bit per pixel saying whether that 596 // pixel is considered to be part of a rooftop or not. 597 string mask_url = 5; 598 599 // The URL for the annual flux map (annual sunlight on roofs) of the region. 600 // Values are kWh/kW/year. This is *unmasked flux*: flux is computed for every 601 // location, not just building rooftops. Invalid locations are stored as 602 // -9999: locations outside our coverage area will be invalid, and a few 603 // locations inside the coverage area, where we were unable to calculate flux, 604 // will also be invalid. 605 string annual_flux_url = 6; 606 607 // The URL for the monthly flux map (sunlight on roofs, broken down by month) 608 // of the region. Values are kWh/kW/year. The GeoTIFF pointed to by this URL 609 // will contain twelve bands, corresponding to January...December, in order. 610 string monthly_flux_url = 7; 611 612 // Twelve URLs for hourly shade, corresponding to January...December, in 613 // order. Each GeoTIFF will contain 24 bands, corresponding to the 24 hours of 614 // the day. Each pixel is a 32 bit integer, corresponding to the (up to) 31 615 // days of that month; a 1 bit means that the corresponding location is able 616 // to see the sun at that day, of that hour, of that month. Invalid locations 617 // are stored as -9999 (since this is negative, it has bit 31 set, and no 618 // valid value could have bit 31 set as that would correspond to the 32nd day 619 // of the month). 620 // 621 // An example may be useful. If you want to know whether a point (at 622 // pixel location (x, y)) saw sun at 4pm on the 22nd of June you 623 // would: 624 // 625 // 1. fetch the sixth URL in this list (corresponding to June). 626 // 1. look up the 17th channel (corresponding to 4pm). 627 // 1. read the 32-bit value at (x, y). 628 // 1. read bit 21 of the value (corresponding to the 22nd of the month). 629 // 1. if that bit is a 1, then that spot saw the sun at 4pm 22 June. 630 // 631 // More formally: 632 // Given `month` (1-12), `day` (1...month max; February has 28 days) 633 // and `hour` (0-23), the shade/sun for that month/day/hour at a 634 // position `(x, y)` is the bit 635 // ``` 636 // (hourly_shade[month - 1])(x, y)[hour] & (1 << (day - 1)) 637 // ``` 638 // where `(x, y)` is spatial indexing, `[month - 1]` refers to 639 // fetching the `month - 1`st URL (indexing from zero), `[hour]` is 640 // indexing into the channels, and a final non-zero result means 641 // "sunny". There are no leap days, and DST doesn't exist (all days 642 // are 24 hours long; noon is always "standard time" noon). 643 repeated string hourly_shade_urls = 8; 644 645 // The quality of the result's imagery. 646 ImageryQuality imagery_quality = 9; 647} 648 649// Request message for `Solar.GetGeoTiff`. 650message GetGeoTiffRequest { 651 // Required. The ID of the asset being requested. 652 string id = 1 [(google.api.field_behavior) = REQUIRED]; 653} 654 655// What subset of the solar information to return. 656enum DataLayerView { 657 // Equivalent to FULL. 658 DATA_LAYER_VIEW_UNSPECIFIED = 0; 659 660 // Get the DSM only. 661 DSM_LAYER = 1; 662 663 // Get the DSM, RGB, and mask. 664 IMAGERY_LAYERS = 2; 665 666 // Get the DSM, RGB, mask, and annual flux. 667 IMAGERY_AND_ANNUAL_FLUX_LAYERS = 3; 668 669 // Get the DSM, RGB, mask, annual flux, and monthly flux. 670 IMAGERY_AND_ALL_FLUX_LAYERS = 4; 671 672 // Get all data. 673 FULL_LAYERS = 5; 674} 675 676// The quality of the imagery used to compute some API result. 677// 678// Note: Regardless of imagery quality level, DSM outputs always have a 679// resolution of 0.1 m/pixel, monthly flux outputs always have a resolution of 680// 0.5 m/pixel, and hourly shade outputs always have a resolution of 1 m/pixel. 681enum ImageryQuality { 682 // No quality is known. 683 IMAGERY_QUALITY_UNSPECIFIED = 0; 684 685 // The underlying imagery and DSM data were processed at 0.1 m/pixel. 686 HIGH = 1; 687 688 // The underlying imagery and DSM data were processed at 0.25 m/pixel. 689 MEDIUM = 2; 690 691 // The underlying imagery and DSM data were processed at 0.5 m/pixel. 692 LOW = 3; 693} 694 695// The orientation of a solar panel. This must be interpreted relative to the 696// azimuth of the roof segment that the panel is placed on. 697enum SolarPanelOrientation { 698 // No panel orientation is known. 699 SOLAR_PANEL_ORIENTATION_UNSPECIFIED = 0; 700 701 // A `LANDSCAPE` panel has its long edge perpendicular to the 702 // azimuth direction of the roof segment that it is placed on. 703 LANDSCAPE = 1; 704 705 // A `PORTRAIT` panel has its long edge parallel to the azimuth 706 // direction of the roof segment that it is placed on. 707 PORTRAIT = 2; 708} 709